mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 21:20:45 +00:00
CE-1955 Initial checkin
This commit is contained in:
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.filehandling;
|
||||
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.BulkLoadFileRow;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for CsvFileToRows
|
||||
*******************************************************************************/
|
||||
class CsvFileToRowsTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
byte[] csvBytes = """
|
||||
one,two,three
|
||||
1,2,3,4
|
||||
""".getBytes();
|
||||
FileToRowsInterface fileToRowsInterface = FileToRowsInterface.forFile("someFile.csv", new ByteArrayInputStream(csvBytes));
|
||||
|
||||
BulkLoadFileRow headerRow = fileToRowsInterface.next();
|
||||
BulkLoadFileRow bodyRow = fileToRowsInterface.next();
|
||||
|
||||
assertEquals(new BulkLoadFileRow(new String[] { "one", "two", "three" }), headerRow);
|
||||
assertEquals(new BulkLoadFileRow(new String[] { "1", "2", "3", "4" }), bodyRow);
|
||||
assertFalse(fileToRowsInterface.hasNext());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.filehandling;
|
||||
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.BulkLoadFileRow;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public class TestFileToRows extends AbstractIteratorBasedFileToRows<Serializable[]> implements FileToRowsInterface
|
||||
{
|
||||
private final List<Serializable[]> rows;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public TestFileToRows(List<Serializable[]> rows)
|
||||
{
|
||||
this.rows = rows;
|
||||
setIterator(this.rows.iterator());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@Override
|
||||
public void init(InputStream inputStream) throws QException
|
||||
{
|
||||
///////////
|
||||
// noop! //
|
||||
///////////
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@Override
|
||||
public void close() throws Exception
|
||||
{
|
||||
///////////
|
||||
// noop! //
|
||||
///////////
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
@Override
|
||||
public BulkLoadFileRow makeRow(Serializable[] values)
|
||||
{
|
||||
return (new BulkLoadFileRow(values));
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.filehandling;
|
||||
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportActionTest;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.excel.fastexcel.ExcelFastexcelExportStreamer;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportDestination;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.BulkLoadFileRow;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportActionTest.REPORT_NAME;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for XlsxFileToRows
|
||||
*******************************************************************************/
|
||||
class XlsxFileToRowsTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
byte[] byteArray = writeExcelBytes();
|
||||
|
||||
FileToRowsInterface fileToRowsInterface = FileToRowsInterface.forFile("someFile.xlsx", new ByteArrayInputStream(byteArray));
|
||||
|
||||
BulkLoadFileRow headerRow = fileToRowsInterface.next();
|
||||
BulkLoadFileRow bodyRow = fileToRowsInterface.next();
|
||||
|
||||
assertEquals(new BulkLoadFileRow(new String[] {"Id", "First Name", "Last Name"}), headerRow);
|
||||
assertEquals(new BulkLoadFileRow(new String[] {"1", "Darin", "Jonson"}), bodyRow);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// make sure there's at least a limit (less than 20) to how many more rows there are //
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
int otherRowCount = 0;
|
||||
while(fileToRowsInterface.hasNext() && otherRowCount < 20)
|
||||
{
|
||||
fileToRowsInterface.next();
|
||||
otherRowCount++;
|
||||
}
|
||||
assertFalse(fileToRowsInterface.hasNext());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private static byte[] writeExcelBytes() throws QException
|
||||
{
|
||||
ReportFormat format = ReportFormat.XLSX;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
QInstance qInstance = QContext.getQInstance();
|
||||
qInstance.addReport(GenerateReportActionTest.defineTableOnlyReport());
|
||||
GenerateReportActionTest.insertPersonRecords(qInstance);
|
||||
|
||||
ReportInput reportInput = new ReportInput();
|
||||
reportInput.setReportName(REPORT_NAME);
|
||||
reportInput.setReportDestination(new ReportDestination().withReportFormat(format).withReportOutputStream(baos));
|
||||
reportInput.setInputValues(Map.of("startDate", LocalDate.of(1970, Month.MAY, 15), "endDate", LocalDate.now()));
|
||||
reportInput.setOverrideExportStreamerSupplier(ExcelFastexcelExportStreamer::new);
|
||||
new GenerateReportAction().execute(reportInput);
|
||||
|
||||
byte[] byteArray = baos.toByteArray();
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.mapping;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.BulkLoadFileRow;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.filehandling.TestFileToRows;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.collections.ListBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for FlatRowsToRecord
|
||||
*******************************************************************************/
|
||||
class FlatRowsToRecordTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testFieldNameToHeaderNameMapping() throws QException
|
||||
{
|
||||
TestFileToRows fileToRows = new TestFileToRows(List.of(
|
||||
new Serializable[] { "id", "firstName", "Last Name", "Ignore", "cost" },
|
||||
new Serializable[] { 1, "Homer", "Simpson", true, "three fifty" },
|
||||
new Serializable[] { 2, "Marge", "Simpson", false, "" },
|
||||
new Serializable[] { 3, "Bart", "Simpson", "A", "99.95" },
|
||||
new Serializable[] { 4, "Ned", "Flanders", 3.1, "one$" }
|
||||
));
|
||||
|
||||
BulkLoadFileRow header = fileToRows.next();
|
||||
|
||||
FlatRowsToRecord rowsToRecord = new FlatRowsToRecord();
|
||||
|
||||
BulkInsertMapping mapping = new BulkInsertMapping()
|
||||
.withFieldNameToHeaderNameMap(Map.of(
|
||||
"firstName", "firstName",
|
||||
"lastName", "Last Name",
|
||||
"cost", "cost"
|
||||
))
|
||||
.withFieldNameToDefaultValueMap(Map.of(
|
||||
"noOfShoes", 2
|
||||
))
|
||||
.withFieldNameToValueMapping(Map.of("cost", Map.of("three fifty", new BigDecimal("3.50"), "one$", new BigDecimal("1.00"))))
|
||||
.withTableName(TestUtils.TABLE_NAME_PERSON)
|
||||
.withHasHeaderRow(true);
|
||||
|
||||
List<QRecord> records = rowsToRecord.nextPage(fileToRows, header, mapping, 1);
|
||||
assertEquals(List.of("Homer"), getValues(records, "firstName"));
|
||||
assertEquals(List.of("Simpson"), getValues(records, "lastName"));
|
||||
assertEquals(List.of(2), getValues(records, "noOfShoes"));
|
||||
assertEquals(List.of(new BigDecimal("3.50")), getValues(records, "cost"));
|
||||
assertEquals(4, records.get(0).getValues().size()); // make sure no additional values were set
|
||||
|
||||
records = rowsToRecord.nextPage(fileToRows, header, mapping, 2);
|
||||
assertEquals(List.of("Marge", "Bart"), getValues(records, "firstName"));
|
||||
assertEquals(List.of(2, 2), getValues(records, "noOfShoes"));
|
||||
assertEquals(ListBuilder.of("", "99.95"), getValues(records, "cost"));
|
||||
|
||||
records = rowsToRecord.nextPage(fileToRows, header, mapping, Integer.MAX_VALUE);
|
||||
assertEquals(List.of("Ned"), getValues(records, "firstName"));
|
||||
assertEquals(List.of(2), getValues(records, "noOfShoes"));
|
||||
assertEquals(ListBuilder.of(new BigDecimal("1.00")), getValues(records, "cost"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testFieldNameToIndexMapping() throws QException
|
||||
{
|
||||
TestFileToRows fileToRows = new TestFileToRows(List.of(
|
||||
new Serializable[] { 1, "Homer", "Simpson", true },
|
||||
new Serializable[] { 2, "Marge", "Simpson", false },
|
||||
new Serializable[] { 3, "Bart", "Simpson", "A" },
|
||||
new Serializable[] { 4, "Ned", "Flanders", 3.1 }
|
||||
));
|
||||
|
||||
BulkLoadFileRow header = null;
|
||||
|
||||
FlatRowsToRecord rowsToRecord = new FlatRowsToRecord();
|
||||
|
||||
BulkInsertMapping mapping = new BulkInsertMapping()
|
||||
.withFieldNameToIndexMap(Map.of(
|
||||
"firstName", 1,
|
||||
"lastName", 2
|
||||
))
|
||||
.withFieldNameToDefaultValueMap(Map.of(
|
||||
"noOfShoes", 2
|
||||
))
|
||||
.withTableName(TestUtils.TABLE_NAME_PERSON)
|
||||
.withHasHeaderRow(false);
|
||||
|
||||
List<QRecord> records = rowsToRecord.nextPage(fileToRows, header, mapping, 1);
|
||||
assertEquals(List.of("Homer"), getValues(records, "firstName"));
|
||||
assertEquals(List.of("Simpson"), getValues(records, "lastName"));
|
||||
assertEquals(List.of(2), getValues(records, "noOfShoes"));
|
||||
assertEquals(3, records.get(0).getValues().size()); // make sure no additional values were set
|
||||
|
||||
records = rowsToRecord.nextPage(fileToRows, header, mapping, 2);
|
||||
assertEquals(List.of("Marge", "Bart"), getValues(records, "firstName"));
|
||||
assertEquals(List.of(2, 2), getValues(records, "noOfShoes"));
|
||||
|
||||
records = rowsToRecord.nextPage(fileToRows, header, mapping, Integer.MAX_VALUE);
|
||||
assertEquals(List.of("Ned"), getValues(records, "firstName"));
|
||||
assertEquals(List.of(2), getValues(records, "noOfShoes"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private List<Serializable> getValues(List<QRecord> records, String fieldName)
|
||||
{
|
||||
return (records.stream().map(r -> r.getValue(fieldName)).toList());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.mapping;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.BulkLoadFileRow;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.filehandling.CsvFileToRows;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for TallRowsToRecord
|
||||
*******************************************************************************/
|
||||
class TallRowsToRecordTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOrderAndLines() throws QException
|
||||
{
|
||||
CsvFileToRows fileToRows = CsvFileToRows.forString("""
|
||||
orderNo, Ship To, lastName, SKU, Quantity
|
||||
1, Homer, Simpson, DONUT, 12
|
||||
, Homer, Simpson, BEER, 500
|
||||
, Homer, Simpson, COUCH, 1
|
||||
2, Ned, Flanders, BIBLE, 7
|
||||
, Ned, Flanders, LAWNMOWER, 1
|
||||
""");
|
||||
|
||||
BulkLoadFileRow header = fileToRows.next();
|
||||
|
||||
TallRowsToRecord rowsToRecord = new TallRowsToRecord();
|
||||
|
||||
BulkInsertMapping mapping = new BulkInsertMapping()
|
||||
.withFieldNameToHeaderNameMap(Map.of(
|
||||
"orderNo", "orderNo",
|
||||
"shipToName", "Ship To",
|
||||
"orderLine.sku", "SKU",
|
||||
"orderLine.quantity", "Quantity"
|
||||
))
|
||||
.withTallLayoutGroupByIndexMap(Map.of(
|
||||
TestUtils.TABLE_NAME_ORDER, List.of(1, 2),
|
||||
"orderLine", List.of(3)
|
||||
))
|
||||
.withMappedAssociations(List.of("orderLine"))
|
||||
.withTableName(TestUtils.TABLE_NAME_ORDER)
|
||||
.withLayout(BulkInsertMapping.Layout.TALL)
|
||||
.withHasHeaderRow(true);
|
||||
|
||||
List<QRecord> records = rowsToRecord.nextPage(fileToRows, header, mapping, Integer.MAX_VALUE);
|
||||
assertEquals(2, records.size());
|
||||
|
||||
QRecord order = records.get(0);
|
||||
assertEquals(1, order.getValueInteger("orderNo"));
|
||||
assertEquals("Homer", order.getValueString("shipToName"));
|
||||
assertEquals(3, order.getAssociatedRecords().get("orderLine").size());
|
||||
assertEquals(List.of("DONUT", "BEER", "COUCH"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("12", "500", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
|
||||
order = records.get(1);
|
||||
assertEquals(2, order.getValueInteger("orderNo"));
|
||||
assertEquals("Ned", order.getValueString("shipToName"));
|
||||
assertEquals(2, order.getAssociatedRecords().get("orderLine").size());
|
||||
assertEquals(List.of("BIBLE", "LAWNMOWER"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("7", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOrderLinesAndOrderExtrinsic() throws QException
|
||||
{
|
||||
CsvFileToRows fileToRows = CsvFileToRows.forString("""
|
||||
orderNo, Ship To, lastName, SKU, Quantity, Extrinsic Key, Extrinsic Value
|
||||
1, Homer, Simpson, DONUT, 12, Store Name, QQQ Mart
|
||||
1, , , BEER, 500, Coupon Code, 10QOff
|
||||
1, , , COUCH, 1
|
||||
2, Ned, Flanders, BIBLE, 7
|
||||
2, , , LAWNMOWER, 1
|
||||
""");
|
||||
|
||||
BulkLoadFileRow header = fileToRows.next();
|
||||
|
||||
TallRowsToRecord rowsToRecord = new TallRowsToRecord();
|
||||
|
||||
BulkInsertMapping mapping = new BulkInsertMapping()
|
||||
.withFieldNameToHeaderNameMap(Map.of(
|
||||
"orderNo", "orderNo",
|
||||
"shipToName", "Ship To",
|
||||
"orderLine.sku", "SKU",
|
||||
"orderLine.quantity", "Quantity",
|
||||
"extrinsics.key", "Extrinsic Key",
|
||||
"extrinsics.value", "Extrinsic Value"
|
||||
))
|
||||
.withTallLayoutGroupByIndexMap(Map.of(
|
||||
TestUtils.TABLE_NAME_ORDER, List.of(0),
|
||||
"orderLine", List.of(3),
|
||||
"extrinsics", List.of(5)
|
||||
))
|
||||
.withMappedAssociations(List.of("orderLine", "extrinsics"))
|
||||
.withTableName(TestUtils.TABLE_NAME_ORDER)
|
||||
.withLayout(BulkInsertMapping.Layout.TALL)
|
||||
.withHasHeaderRow(true);
|
||||
|
||||
List<QRecord> records = rowsToRecord.nextPage(fileToRows, header, mapping, Integer.MAX_VALUE);
|
||||
assertEquals(2, records.size());
|
||||
|
||||
QRecord order = records.get(0);
|
||||
assertEquals(1, order.getValueInteger("orderNo"));
|
||||
assertEquals("Homer", order.getValueString("shipToName"));
|
||||
assertEquals(3, order.getAssociatedRecords().get("orderLine").size());
|
||||
assertEquals(List.of("DONUT", "BEER", "COUCH"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("12", "500", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
assertEquals(2, order.getAssociatedRecords().get("extrinsics").size());
|
||||
assertEquals(List.of("Store Name", "Coupon Code"), getValues(order.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("QQQ Mart", "10QOff"), getValues(order.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
|
||||
order = records.get(1);
|
||||
assertEquals(2, order.getValueInteger("orderNo"));
|
||||
assertEquals("Ned", order.getValueString("shipToName"));
|
||||
assertEquals(2, order.getAssociatedRecords().get("orderLine").size());
|
||||
assertEquals(List.of("BIBLE", "LAWNMOWER"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("7", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
assertThat(order.getAssociatedRecords().get("extrinsics")).isNullOrEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOrderLinesWithLineExtrinsicsAndOrderExtrinsic() throws QException
|
||||
{
|
||||
Integer DEFAULT_STORE_ID = 101;
|
||||
Integer DEFAULT_LINE_NO = 102;
|
||||
String DEFAULT_ORDER_LINE_EXTRA_SOURCE = "file";
|
||||
|
||||
CsvFileToRows fileToRows = CsvFileToRows.forString("""
|
||||
orderNo, Ship To, lastName, SKU, Quantity, Extrinsic Key, Extrinsic Value, Line Extrinsic Key, Line Extrinsic Value
|
||||
1, Homer, Simpson, DONUT, 12, Store Name, QQQ Mart, Flavor, Chocolate
|
||||
1, , , DONUT, , Coupon Code, 10QOff, Size, Large
|
||||
1, , , BEER, 500, , , Flavor, Hops
|
||||
1, , , COUCH, 1
|
||||
2, Ned, Flanders, BIBLE, 7, , , Flavor, King James
|
||||
2, , , LAWNMOWER, 1
|
||||
""");
|
||||
|
||||
BulkLoadFileRow header = fileToRows.next();
|
||||
|
||||
TallRowsToRecord rowsToRecord = new TallRowsToRecord();
|
||||
|
||||
BulkInsertMapping mapping = new BulkInsertMapping()
|
||||
.withFieldNameToHeaderNameMap(Map.of(
|
||||
"orderNo", "orderNo",
|
||||
"shipToName", "Ship To",
|
||||
"orderLine.sku", "SKU",
|
||||
"orderLine.quantity", "Quantity",
|
||||
"extrinsics.key", "Extrinsic Key",
|
||||
"extrinsics.value", "Extrinsic Value",
|
||||
"orderLine.extrinsics.key", "Line Extrinsic Key",
|
||||
"orderLine.extrinsics.value", "Line Extrinsic Value"
|
||||
))
|
||||
.withFieldNameToDefaultValueMap(Map.of(
|
||||
"storeId", DEFAULT_STORE_ID,
|
||||
"orderLine.lineNumber", DEFAULT_LINE_NO,
|
||||
"orderLine.extrinsics.source", DEFAULT_ORDER_LINE_EXTRA_SOURCE
|
||||
))
|
||||
.withFieldNameToValueMapping(Map.of("orderLine.sku", Map.of("DONUT", "D'OH-NUT")))
|
||||
.withTallLayoutGroupByIndexMap(Map.of(
|
||||
TestUtils.TABLE_NAME_ORDER, List.of(0),
|
||||
"orderLine", List.of(3),
|
||||
"extrinsics", List.of(5),
|
||||
"orderLine.extrinsics", List.of(7)
|
||||
))
|
||||
.withMappedAssociations(List.of("orderLine", "extrinsics", "orderLine.extrinsics"))
|
||||
.withTableName(TestUtils.TABLE_NAME_ORDER)
|
||||
.withLayout(BulkInsertMapping.Layout.TALL)
|
||||
.withHasHeaderRow(true);
|
||||
|
||||
List<QRecord> records = rowsToRecord.nextPage(fileToRows, header, mapping, Integer.MAX_VALUE);
|
||||
assertEquals(2, records.size());
|
||||
|
||||
QRecord order = records.get(0);
|
||||
assertEquals(1, order.getValueInteger("orderNo"));
|
||||
assertEquals("Homer", order.getValueString("shipToName"));
|
||||
assertEquals(DEFAULT_STORE_ID, order.getValue("storeId"));
|
||||
assertEquals(List.of("D'OH-NUT", "BEER", "COUCH"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("12", "500", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
assertEquals(List.of(DEFAULT_LINE_NO, DEFAULT_LINE_NO, DEFAULT_LINE_NO), getValues(order.getAssociatedRecords().get("orderLine"), "lineNumber"));
|
||||
assertEquals(List.of("Store Name", "Coupon Code"), getValues(order.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("QQQ Mart", "10QOff"), getValues(order.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
|
||||
QRecord lineItem = order.getAssociatedRecords().get("orderLine").get(0);
|
||||
assertEquals(List.of("Flavor", "Size"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("Chocolate", "Large"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
assertEquals(List.of(DEFAULT_ORDER_LINE_EXTRA_SOURCE, DEFAULT_ORDER_LINE_EXTRA_SOURCE), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "source"));
|
||||
|
||||
lineItem = order.getAssociatedRecords().get("orderLine").get(1);
|
||||
assertEquals(List.of("Flavor"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("Hops"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
|
||||
order = records.get(1);
|
||||
assertEquals(2, order.getValueInteger("orderNo"));
|
||||
assertEquals("Ned", order.getValueString("shipToName"));
|
||||
assertEquals(DEFAULT_STORE_ID, order.getValue("storeId"));
|
||||
assertEquals(List.of("BIBLE", "LAWNMOWER"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("7", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
assertEquals(List.of(DEFAULT_LINE_NO, DEFAULT_LINE_NO), getValues(order.getAssociatedRecords().get("orderLine"), "lineNumber"));
|
||||
assertThat(order.getAssociatedRecords().get("extrinsics")).isNullOrEmpty();
|
||||
|
||||
lineItem = order.getAssociatedRecords().get("orderLine").get(0);
|
||||
assertEquals(List.of("Flavor"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("King James"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
assertEquals(List.of(DEFAULT_ORDER_LINE_EXTRA_SOURCE), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "source"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testShouldProcessAssociation()
|
||||
{
|
||||
TallRowsToRecord tallRowsToRecord = new TallRowsToRecord();
|
||||
assertTrue(tallRowsToRecord.shouldProcessAssociation(null, "foo"));
|
||||
assertTrue(tallRowsToRecord.shouldProcessAssociation("", "foo"));
|
||||
assertTrue(tallRowsToRecord.shouldProcessAssociation("foo", "foo.bar"));
|
||||
assertTrue(tallRowsToRecord.shouldProcessAssociation("foo.bar", "foo.bar.baz"));
|
||||
|
||||
assertFalse(tallRowsToRecord.shouldProcessAssociation(null, "foo.bar"));
|
||||
assertFalse(tallRowsToRecord.shouldProcessAssociation("", "foo.bar"));
|
||||
assertFalse(tallRowsToRecord.shouldProcessAssociation("fiz", "foo.bar"));
|
||||
assertFalse(tallRowsToRecord.shouldProcessAssociation("fiz.biz", "foo.bar"));
|
||||
assertFalse(tallRowsToRecord.shouldProcessAssociation("foo", "foo.bar.baz"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private List<Serializable> getValues(List<QRecord> records, String fieldName)
|
||||
{
|
||||
return (records.stream().map(r -> r.getValue(fieldName)).toList());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.mapping;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for ValueMapper
|
||||
*******************************************************************************/
|
||||
class ValueMapperTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test()
|
||||
{
|
||||
BulkInsertMapping mapping = new BulkInsertMapping().withFieldNameToValueMapping(Map.of(
|
||||
"storeId", Map.of("QQQMart", 1, "Q'R'Us", 2),
|
||||
"shipToName", Map.of("HoJu", "Homer", "Bart", "Bartholomew"),
|
||||
"lineItem.sku", Map.of("ABC", "Alphabet"),
|
||||
"lineItem.extrinsics.value", Map.of("foo", "bar", "bar", "baz"),
|
||||
"extrinsics.key", Map.of("1", "one", "2", "two")
|
||||
));
|
||||
|
||||
QRecord inputRecord = new QRecord()
|
||||
.withValue("storeId", "QQQMart")
|
||||
.withValue("shipToName", "HoJu")
|
||||
.withAssociatedRecord("lineItem", new QRecord()
|
||||
.withValue("sku", "ABC")
|
||||
.withAssociatedRecord("extrinsics", new QRecord()
|
||||
.withValue("key", "myKey")
|
||||
.withValue("value", "foo")
|
||||
)
|
||||
.withAssociatedRecord("extrinsics", new QRecord()
|
||||
.withValue("key", "yourKey")
|
||||
.withValue("value", "bar")
|
||||
)
|
||||
)
|
||||
.withAssociatedRecord("extrinsics", new QRecord()
|
||||
.withValue("key", 1)
|
||||
.withValue("value", "foo")
|
||||
);
|
||||
JSONObject beforeJson = recordToJson(inputRecord);
|
||||
|
||||
QRecord expectedRecord = new QRecord()
|
||||
.withValue("storeId", 1)
|
||||
.withValue("shipToName", "Homer")
|
||||
.withAssociatedRecord("lineItem", new QRecord()
|
||||
.withValue("sku", "Alphabet")
|
||||
.withAssociatedRecord("extrinsics", new QRecord()
|
||||
.withValue("key", "myKey")
|
||||
.withValue("value", "bar")
|
||||
)
|
||||
.withAssociatedRecord("extrinsics", new QRecord()
|
||||
.withValue("key", "yourKey")
|
||||
.withValue("value", "baz")
|
||||
)
|
||||
)
|
||||
.withAssociatedRecord("extrinsics", new QRecord()
|
||||
.withValue("key", "one")
|
||||
.withValue("value", "foo")
|
||||
);
|
||||
JSONObject expectedJson = recordToJson(expectedRecord);
|
||||
|
||||
ValueMapper.valueMapping(List.of(inputRecord), mapping);
|
||||
JSONObject actualJson = recordToJson(inputRecord);
|
||||
|
||||
System.out.println("Before");
|
||||
System.out.println(beforeJson.toString(3));
|
||||
System.out.println("Actual");
|
||||
System.out.println(actualJson.toString(3));
|
||||
System.out.println("Expected");
|
||||
System.out.println(expectedJson.toString(3));
|
||||
|
||||
assertThat(actualJson).usingRecursiveComparison().isEqualTo(expectedJson);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public static JSONObject recordToJson(QRecord record)
|
||||
{
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
for(Map.Entry<String, Serializable> valueEntry : CollectionUtils.nonNullMap(record.getValues()).entrySet())
|
||||
{
|
||||
jsonObject.put(valueEntry.getKey(), valueEntry.getValue());
|
||||
}
|
||||
for(Map.Entry<String, List<QRecord>> associationEntry : CollectionUtils.nonNullMap(record.getAssociatedRecords()).entrySet())
|
||||
{
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for(QRecord associationRecord : CollectionUtils.nonNullList(associationEntry.getValue()))
|
||||
{
|
||||
jsonArray.put(recordToJson(associationRecord));
|
||||
}
|
||||
jsonObject.put(associationEntry.getKey(), jsonArray);
|
||||
}
|
||||
return (jsonObject);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,305 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.mapping;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.BulkLoadFileRow;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.filehandling.CsvFileToRows;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for WideRowsToRecord
|
||||
*******************************************************************************/
|
||||
class WideRowsToRecordTest extends BaseTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOrderAndLinesWithoutDupes() throws QException
|
||||
{
|
||||
testOrderAndLines("""
|
||||
orderNo, Ship To, lastName, SKU 1, Quantity 1, SKU 2, Quantity 2, SKU 3, Quantity 3
|
||||
1, Homer, Simpson, DONUT, 12, BEER, 500, COUCH, 1
|
||||
2, Ned, Flanders, BIBLE, 7, LAWNMOWER, 1
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOrderAndLinesWithDupes() throws QException
|
||||
{
|
||||
testOrderAndLines("""
|
||||
orderNo, Ship To, lastName, SKU, Quantity, SKU, Quantity, SKU, Quantity
|
||||
1, Homer, Simpson, DONUT, 12, BEER, 500, COUCH, 1
|
||||
2, Ned, Flanders, BIBLE, 7, LAWNMOWER, 1
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private void testOrderAndLines(String csv) throws QException
|
||||
{
|
||||
CsvFileToRows fileToRows = CsvFileToRows.forString(csv);
|
||||
BulkLoadFileRow header = fileToRows.next();
|
||||
|
||||
WideRowsToRecord rowsToRecord = new WideRowsToRecord();
|
||||
|
||||
BulkInsertMapping mapping = new BulkInsertMapping()
|
||||
.withFieldNameToHeaderNameMap(Map.of(
|
||||
"orderNo", "orderNo",
|
||||
"shipToName", "Ship To",
|
||||
"orderLine.sku", "SKU",
|
||||
"orderLine.quantity", "Quantity"
|
||||
))
|
||||
.withMappedAssociations(List.of("orderLine"))
|
||||
.withTableName(TestUtils.TABLE_NAME_ORDER)
|
||||
.withLayout(BulkInsertMapping.Layout.WIDE)
|
||||
.withHasHeaderRow(true);
|
||||
|
||||
List<QRecord> records = rowsToRecord.nextPage(fileToRows, header, mapping, Integer.MAX_VALUE);
|
||||
assertEquals(2, records.size());
|
||||
|
||||
QRecord order = records.get(0);
|
||||
assertEquals(1, order.getValueInteger("orderNo"));
|
||||
assertEquals("Homer", order.getValueString("shipToName"));
|
||||
assertEquals(List.of("DONUT", "BEER", "COUCH"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("12", "500", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
|
||||
order = records.get(1);
|
||||
assertEquals(2, order.getValueInteger("orderNo"));
|
||||
assertEquals("Ned", order.getValueString("shipToName"));
|
||||
assertEquals(List.of("BIBLE", "LAWNMOWER"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("7", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOrderLinesAndOrderExtrinsicWithoutDupes() throws QException
|
||||
{
|
||||
testOrderLinesAndOrderExtrinsic("""
|
||||
orderNo, Ship To, lastName, SKU 1, Quantity 1, SKU 2, Quantity 2, SKU 3, Quantity 3, Extrinsic Key 1, Extrinsic Value 1, Extrinsic Key 2, Extrinsic Value 2
|
||||
1, Homer, Simpson, DONUT, 12, BEER, 500, COUCH, 1, Store Name, QQQ Mart, Coupon Code, 10QOff
|
||||
2, Ned, Flanders, BIBLE, 7, LAWNMOWER, 1
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOrderLinesAndOrderExtrinsicWithDupes() throws QException
|
||||
{
|
||||
testOrderLinesAndOrderExtrinsic("""
|
||||
orderNo, Ship To, lastName, SKU, Quantity, SKU, Quantity, SKU, Quantity, Extrinsic Key, Extrinsic Value, Extrinsic Key, Extrinsic Value
|
||||
1, Homer, Simpson, DONUT, 12, BEER, 500, COUCH, 1, Store Name, QQQ Mart, Coupon Code, 10QOff
|
||||
2, Ned, Flanders, BIBLE, 7, LAWNMOWER, 1
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void testOrderLinesAndOrderExtrinsic(String csv) throws QException
|
||||
{
|
||||
CsvFileToRows fileToRows = CsvFileToRows.forString(csv);
|
||||
BulkLoadFileRow header = fileToRows.next();
|
||||
|
||||
WideRowsToRecord rowsToRecord = new WideRowsToRecord();
|
||||
|
||||
BulkInsertMapping mapping = new BulkInsertMapping()
|
||||
.withFieldNameToHeaderNameMap(Map.of(
|
||||
"orderNo", "orderNo",
|
||||
"shipToName", "Ship To",
|
||||
"orderLine.sku", "SKU",
|
||||
"orderLine.quantity", "Quantity",
|
||||
"extrinsics.key", "Extrinsic Key",
|
||||
"extrinsics.value", "Extrinsic Value"
|
||||
))
|
||||
.withMappedAssociations(List.of("orderLine", "extrinsics"))
|
||||
.withTableName(TestUtils.TABLE_NAME_ORDER)
|
||||
.withLayout(BulkInsertMapping.Layout.WIDE)
|
||||
.withHasHeaderRow(true);
|
||||
|
||||
List<QRecord> records = rowsToRecord.nextPage(fileToRows, header, mapping, Integer.MAX_VALUE);
|
||||
assertEquals(2, records.size());
|
||||
|
||||
QRecord order = records.get(0);
|
||||
assertEquals(1, order.getValueInteger("orderNo"));
|
||||
assertEquals("Homer", order.getValueString("shipToName"));
|
||||
assertEquals(List.of("DONUT", "BEER", "COUCH"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("12", "500", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
assertEquals(List.of("Store Name", "Coupon Code"), getValues(order.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("QQQ Mart", "10QOff"), getValues(order.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
|
||||
order = records.get(1);
|
||||
assertEquals(2, order.getValueInteger("orderNo"));
|
||||
assertEquals("Ned", order.getValueString("shipToName"));
|
||||
assertEquals(List.of("BIBLE", "LAWNMOWER"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("7", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
assertThat(order.getAssociatedRecords().get("extrinsics")).isNullOrEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOrderLinesWithLineExtrinsicsAndOrderExtrinsicWithoutDupes() throws QException
|
||||
{
|
||||
testOrderLinesWithLineExtrinsicsAndOrderExtrinsic("""
|
||||
orderNo, Ship To, lastName, Extrinsic Key 1, Extrinsic Value 1, Extrinsic Key 2, Extrinsic Value 2, SKU 1, Quantity 1, Line Extrinsic Key 1, Line Extrinsic Value 1, Line Extrinsic Key 2, Line Extrinsic Value 2, SKU 2, Quantity 2, Line Extrinsic Key 1, Line Extrinsic Value 1, SKU 3, Quantity 3, Line Extrinsic Key 1, Line Extrinsic Value 1, Line Extrinsic Key 2
|
||||
1, Homer, Simpson, Store Name, QQQ Mart, Coupon Code, 10QOff, DONUT, 12, Flavor, Chocolate, Size, Large, BEER, 500, Flavor, Hops, COUCH, 1, Color, Brown, foo,
|
||||
2, Ned, Flanders, , , , , BIBLE, 7, Flavor, King James, Size, X-Large, LAWNMOWER, 1
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOrderLinesWithLineExtrinsicsAndOrderExtrinsicWithDupes() throws QException
|
||||
{
|
||||
testOrderLinesWithLineExtrinsicsAndOrderExtrinsic("""
|
||||
orderNo, Ship To, lastName, Extrinsic Key, Extrinsic Value, Extrinsic Key, Extrinsic Value, SKU, Quantity, Line Extrinsic Key, Line Extrinsic Value, Line Extrinsic Key, Line Extrinsic Value, SKU, Quantity, Line Extrinsic Key, Line Extrinsic Value, SKU, Quantity, Line Extrinsic Key, Line Extrinsic Value, Line Extrinsic Key
|
||||
1, Homer, Simpson, Store Name, QQQ Mart, Coupon Code, 10QOff, DONUT, 12, Flavor, Chocolate, Size, Large, BEER, 500, Flavor, Hops, COUCH, 1, Color, Brown, foo
|
||||
2, Ned, Flanders, , , , , BIBLE, 7, Flavor, King James, Size, X-Large, LAWNMOWER, 1
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private void testOrderLinesWithLineExtrinsicsAndOrderExtrinsic(String csv) throws QException
|
||||
{
|
||||
Integer DEFAULT_STORE_ID = 42;
|
||||
Integer DEFAULT_LINE_NO = 47;
|
||||
String DEFAULT_LINE_EXTRA_VALUE = "bar";
|
||||
|
||||
CsvFileToRows fileToRows = CsvFileToRows.forString(csv);
|
||||
BulkLoadFileRow header = fileToRows.next();
|
||||
|
||||
WideRowsToRecord rowsToRecord = new WideRowsToRecord();
|
||||
|
||||
BulkInsertMapping mapping = new BulkInsertMapping()
|
||||
.withFieldNameToHeaderNameMap(Map.of(
|
||||
"orderNo", "orderNo",
|
||||
"shipToName", "Ship To",
|
||||
"orderLine.sku", "SKU",
|
||||
"orderLine.quantity", "Quantity",
|
||||
"extrinsics.key", "Extrinsic Key",
|
||||
"extrinsics.value", "Extrinsic Value",
|
||||
"orderLine.extrinsics.key", "Line Extrinsic Key",
|
||||
"orderLine.extrinsics.value", "Line Extrinsic Value"
|
||||
))
|
||||
.withMappedAssociations(List.of("orderLine", "extrinsics", "orderLine.extrinsics"))
|
||||
.withFieldNameToValueMapping(Map.of("orderLine.extrinsics.value", Map.of("Large", "L", "X-Large", "XL")))
|
||||
.withFieldNameToDefaultValueMap(Map.of(
|
||||
"storeId", DEFAULT_STORE_ID,
|
||||
"orderLine.lineNumber", DEFAULT_LINE_NO,
|
||||
"orderLine.extrinsics.value", DEFAULT_LINE_EXTRA_VALUE
|
||||
))
|
||||
.withTableName(TestUtils.TABLE_NAME_ORDER)
|
||||
.withLayout(BulkInsertMapping.Layout.WIDE)
|
||||
.withHasHeaderRow(true);
|
||||
|
||||
List<QRecord> records = rowsToRecord.nextPage(fileToRows, header, mapping, Integer.MAX_VALUE);
|
||||
assertEquals(2, records.size());
|
||||
|
||||
QRecord order = records.get(0);
|
||||
assertEquals(1, order.getValueInteger("orderNo"));
|
||||
assertEquals("Homer", order.getValueString("shipToName"));
|
||||
assertEquals(DEFAULT_STORE_ID, order.getValue("storeId"));
|
||||
assertEquals(List.of("DONUT", "BEER", "COUCH"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("12", "500", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
assertEquals(List.of(DEFAULT_LINE_NO, DEFAULT_LINE_NO, DEFAULT_LINE_NO), getValues(order.getAssociatedRecords().get("orderLine"), "lineNumber"));
|
||||
assertEquals(List.of("Store Name", "Coupon Code"), getValues(order.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("QQQ Mart", "10QOff"), getValues(order.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
|
||||
QRecord lineItem = order.getAssociatedRecords().get("orderLine").get(0);
|
||||
assertEquals(List.of("Flavor", "Size"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("Chocolate", "L"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
|
||||
lineItem = order.getAssociatedRecords().get("orderLine").get(1);
|
||||
assertEquals(List.of("Flavor"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("Hops"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
|
||||
lineItem = order.getAssociatedRecords().get("orderLine").get(2);
|
||||
assertEquals(List.of("Color", "foo"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("Brown", DEFAULT_LINE_EXTRA_VALUE), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
|
||||
order = records.get(1);
|
||||
assertEquals(2, order.getValueInteger("orderNo"));
|
||||
assertEquals("Ned", order.getValueString("shipToName"));
|
||||
assertEquals(DEFAULT_STORE_ID, order.getValue("storeId"));
|
||||
assertEquals(List.of("BIBLE", "LAWNMOWER"), getValues(order.getAssociatedRecords().get("orderLine"), "sku"));
|
||||
assertEquals(List.of("7", "1"), getValues(order.getAssociatedRecords().get("orderLine"), "quantity"));
|
||||
assertEquals(List.of(DEFAULT_LINE_NO, DEFAULT_LINE_NO), getValues(order.getAssociatedRecords().get("orderLine"), "lineNumber"));
|
||||
assertThat(order.getAssociatedRecords().get("extrinsics")).isNullOrEmpty();
|
||||
|
||||
lineItem = order.getAssociatedRecords().get("orderLine").get(0);
|
||||
assertEquals(List.of("Flavor", "Size"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "key"));
|
||||
assertEquals(List.of("King James", "XL"), getValues(lineItem.getAssociatedRecords().get("extrinsics"), "value"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private List<Serializable> getValues(List<QRecord> records, String fieldName)
|
||||
{
|
||||
return (records.stream().map(r -> r.getValue(fieldName)).toList());
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user