From a4bd3a68ecc6f7d360ab751be88b22324249b6f6 Mon Sep 17 00:00:00 2001 From: Paul Rill Date: Mon, 4 Mar 2024 14:36:33 +0100 Subject: [PATCH 1/4] feat: :sparkles: allow for uploading CSVs to a Batch --- src/models/Batch.ts | 29 ++++++++++++++++++++ src/models/CsvOrder.ts | 2 ++ test/Batch.spec.ts | 62 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/models/Batch.ts b/src/models/Batch.ts index 1687a2b..abc7da8 100644 --- a/src/models/Batch.ts +++ b/src/models/Batch.ts @@ -7,6 +7,8 @@ import { PaginatedResponse } from "./PaginatedResponse"; import { Order } from "./Order"; import { Address } from "./Address"; import { IOrder } from "./_interfaces/IOrder"; +import { CreateBatchCsvOrder, CsvOrder } from "./CsvOrder"; +import { ICsvOrder } from "./_interfaces/ICsvOrder"; export type CreateBatch = { name: string; @@ -144,6 +146,33 @@ export class Batch { return new Order(this._protected, data); } + public async createCsvOrder(data: CreateBatchCsvOrder): Promise { + const formData = new FormData(); + formData.append( + "file", + new Blob([data.file], { type: "text/csv" }), + "upload.csv", + ); + formData.append("mapping", JSON.stringify(data.mapping)); + + const response = await this._protected.client.POST<{ id: string }>( + `/batches/${this.id}/orders/csv`, + formData, + { + headers: { + "Content-Type": "multipart/form-data", + }, + }, + ); + + const id = response.id; + const csvInfo = await this._protected.client.GET( + `batches/${this.id}/orders/csv/${id}`, + ); + + return new CsvOrder(this._protected, csvInfo); + } + /** * Update the batch * diff --git a/src/models/CsvOrder.ts b/src/models/CsvOrder.ts index 7e36250..9827cea 100644 --- a/src/models/CsvOrder.ts +++ b/src/models/CsvOrder.ts @@ -20,6 +20,8 @@ export type CreateCsvOrder = { sender?: Address; }; +export type CreateBatchCsvOrder = Pick; + export class CsvOrder { private _data: ICsvOrder; diff --git a/test/Batch.spec.ts b/test/Batch.spec.ts index 6e65227..cd23dfc 100644 --- a/test/Batch.spec.ts +++ b/test/Batch.spec.ts @@ -1,5 +1,7 @@ import { Batch, + CreateBatchCsvOrder, + CsvOrder, Finish, Format, Order, @@ -8,6 +10,8 @@ import { } from "../src"; import { client } from "./client"; import { BatchStatus } from "../src/enums/BatchStatus"; +import * as fs from "fs"; +import * as path from "path"; let batch: Batch = null as unknown as Batch; let template: Template = null as unknown as Template; @@ -29,10 +33,6 @@ beforeEach(async function () { }); }); -afterAll(async function () { - await template.delete(); -}); - async function addOrders(count: number): Promise { await Promise.all( Array.from(Array(count)).map(() => @@ -85,6 +85,60 @@ describe("createOrder", function () { }, 20000); }); +describe("createCsvOrder", function () { + let file: ArrayBuffer = null as unknown as ArrayBuffer; + + const mapping: CreateBatchCsvOrder["mapping"] = { + recipient: { + city: "{{City}}", + name: "{{FirstName}} {{LastName}}", + address: "{{Street}} {{HouseNr}}", + country: "{{Country}}", + postalCode: "{{ZIP}}", + }, + }; + + beforeAll(() => { + file = fs.readFileSync(path.join(__dirname, "assets/test.csv")); + }); + + it("should create a csv order with all fields", async function () { + // arrange + + // act + const csvOrder = await batch.createCsvOrder({ + mapping: mapping, + file: file, + }); + + // assert + expect(csvOrder).toBeDefined(); + expect(csvOrder).toEqual(expect.any(CsvOrder)); + + expect(csvOrder.id).toEqual(expect.any(String)); + expect(csvOrder.status).toEqual(expect.any(String)); + expect(csvOrder.createdAt).toEqual(expect.any(Date)); + expect(csvOrder.updatedAt).toEqual(expect.any(Date)); + // if sendDate is undefined, it should be today + expect(csvOrder.sendDate.getDay()).toEqual(new Date().getDay()); + expect(csvOrder.friendlyStatus).toEqual(expect.any(String)); + expect(csvOrder.sender).toEqual(undefined); + expect(csvOrder.recipientMapping).toEqual(mapping.recipient); + expect(csvOrder.templateId).toEqual(template.id); + expect(csvOrder.mergeVariableMapping).toEqual(mapping.mergeVariables); + expect(csvOrder.billingId).toEqual( + expect.toBeOneOf([undefined, expect.any(String)]), + ); + expect(csvOrder.finish).toEqual(expect.any(String)); + expect(csvOrder.format).toEqual(expect.any(String)); + expect(csvOrder.isBillable).toEqual(expect.any(Boolean)); + expect(csvOrder.estimatedOrderCount).toEqual(expect.any(Number)); + expect(csvOrder.failedOrderCount).toEqual(expect.any(Number)); + expect(csvOrder.processedOrderCount).toEqual(expect.any(Number)); + expect(csvOrder.totalOrderCount).toEqual(expect.any(Number)); + }); +}); + describe("update", function () { describe("ready", function () { it("should update the batch to ready", async function () { From 0560944128abdeea5cf0ff5ec79391201e0598a3 Mon Sep 17 00:00:00 2001 From: Paul Rill Date: Thu, 7 Mar 2024 10:43:50 +0100 Subject: [PATCH 2/4] feat: :sparkles: allow for getting CSV order by id --- docs/Batch.md | 59 +++++++++++++++++++++++++++++++++++++++++++ src/models/Batch.ts | 10 ++++++++ test/Batch.spec.ts | 53 ++++++++++++++++++++++++++++++++++++++ test/PrintOne.spec.ts | 2 +- 4 files changed, 123 insertions(+), 1 deletion(-) diff --git a/docs/Batch.md b/docs/Batch.md index d5a8c06..c91d313 100644 --- a/docs/Batch.md +++ b/docs/Batch.md @@ -162,3 +162,62 @@ await batch.update({ ready: true, }); ``` + +--- + +## `.createCsvOrder(data)` + +Create a new csv order. + +**Parameters** + +| Name | Type | Description | +| ------ | -------- | ------------------------------------------------------------------------------------------------- | +| `data` | `object` | The data to create the order with. See [`CsvOrder`](./CsvOrder#createcsvorderdata) for more info. | + +**Returns: [`Promise`](./CsvOrder)** + +**Example** + +```js +const batch: Batch; + +const order = await batch.createCsvOrder({ + mapping: { + recipient: { + city: "{{City}}", + name: "{{FirstName}} {{LastName}}", + address: "{{Street}} {{HouseNr}}", + country: "{{Country}}", + postalCode: "{{ZIP}}", + }, + mergeVariables: { + name: "{{FirstName}}", + coupon: "{{Coupon}}", + }, + }, + file: file, +}); +``` + +--- + +## `.getCsvOrder(id)` + +Get a csv order by its ID. + +**Parameters** + +| Name | Type | Description | +| ---- | -------- | ------------------------------- | +| `id` | `string` | The ID of the csv order to get. | + +**Returns: [`Promise`](./CsvOrder)** + +**Example** + +```js +const batch: Batch; + +const csvOrder = await batch.getCsvOrder("example-order-id"); +``` diff --git a/src/models/Batch.ts b/src/models/Batch.ts index abc7da8..f0e0ae8 100644 --- a/src/models/Batch.ts +++ b/src/models/Batch.ts @@ -173,6 +173,16 @@ export class Batch { return new CsvOrder(this._protected, csvInfo); } + /** + * Get a csv order by its id. + * @param { string } id The id of the csv order. + * @param basePath The basePath to use for this request + * @throws { PrintOneError } If the order could not be found. + */ + public async getCsvOrder(id: string): Promise { + return this._protected.printOne.getCsvOrder(id, `batches/${this.id}`); + } + /** * Update the batch * diff --git a/test/Batch.spec.ts b/test/Batch.spec.ts index cd23dfc..c8315ac 100644 --- a/test/Batch.spec.ts +++ b/test/Batch.spec.ts @@ -139,6 +139,59 @@ describe("createCsvOrder", function () { }); }); +describe("getCsvOrder", function () { + let csvOrderId: string = null as unknown as string; + const mapping: CreateBatchCsvOrder["mapping"] = { + recipient: { + city: "{{City}}", + name: "{{FirstName}} {{LastName}}", + address: "{{Street}} {{HouseNr}}", + country: "{{Country}}", + postalCode: "{{ZIP}}", + }, + }; + + beforeAll(async () => { + const file = fs.readFileSync(path.join(__dirname, "assets/test.csv")); + + const csvOrder = await batch.createCsvOrder({ + mapping: mapping, + file: file, + }); + + csvOrderId = csvOrder.id; + }); + + it("should get a csv order with all fields", async function () { + // arrange + + // act + const csvOrder = await client.getCsvOrder(csvOrderId); + + // assert + expect(csvOrder).toBeDefined(); + expect(csvOrder.id).toEqual(expect.any(String)); + expect(csvOrder.status).toEqual(expect.any(String)); + expect(csvOrder.createdAt).toEqual(expect.any(Date)); + expect(csvOrder.updatedAt).toEqual(expect.any(Date)); + // if sendDate is undefined, it should be today + expect(csvOrder.sendDate.getDay()).toEqual(new Date().getDay()); + expect(csvOrder.friendlyStatus).toEqual(expect.any(String)); + expect(csvOrder.sender).toEqual(undefined); + expect(csvOrder.recipientMapping).toEqual(mapping.recipient); + expect(csvOrder.templateId).toEqual(template.id); + expect(csvOrder.mergeVariableMapping).toEqual(mapping.mergeVariables); + expect(csvOrder.billingId).toEqual(undefined); + expect(csvOrder.finish).toEqual(expect.any(String)); + expect(csvOrder.format).toEqual(expect.any(String)); + expect(csvOrder.isBillable).toEqual(expect.any(Boolean)); + expect(csvOrder.estimatedOrderCount).toEqual(expect.any(Number)); + expect(csvOrder.failedOrderCount).toEqual(expect.any(Number)); + expect(csvOrder.processedOrderCount).toEqual(expect.any(Number)); + expect(csvOrder.totalOrderCount).toEqual(expect.any(Number)); + }); +}); + describe("update", function () { describe("ready", function () { it("should update the batch to ready", async function () { diff --git a/test/PrintOne.spec.ts b/test/PrintOne.spec.ts index a3895c8..e273550 100644 --- a/test/PrintOne.spec.ts +++ b/test/PrintOne.spec.ts @@ -854,7 +854,7 @@ describe("getCsvOrder", function () { expect(csvOrder.processedOrderCount).toEqual(expect.any(Number)); expect(csvOrder.totalOrderCount).toEqual(expect.any(Number)); }); -}) +}); describe("getOrder", function () { let orderId: string = null as unknown as string; From 8420046c3655a0a9480f192f3879fcf9524c06f4 Mon Sep 17 00:00:00 2001 From: Paul Rill Date: Mon, 11 Mar 2024 08:03:38 +0100 Subject: [PATCH 3/4] feat: implement PR feedback --- test/Batch.spec.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/Batch.spec.ts b/test/Batch.spec.ts index c8315ac..04b1d8c 100644 --- a/test/Batch.spec.ts +++ b/test/Batch.spec.ts @@ -90,11 +90,12 @@ describe("createCsvOrder", function () { const mapping: CreateBatchCsvOrder["mapping"] = { recipient: { - city: "{{City}}", name: "{{FirstName}} {{LastName}}", + addressLine2: "Financial Dpt.", address: "{{Street}} {{HouseNr}}", - country: "{{Country}}", postalCode: "{{ZIP}}", + city: "{{City}}", + country: "{{Country}}", }, }; @@ -143,11 +144,11 @@ describe("getCsvOrder", function () { let csvOrderId: string = null as unknown as string; const mapping: CreateBatchCsvOrder["mapping"] = { recipient: { - city: "{{City}}", name: "{{FirstName}} {{LastName}}", address: "{{Street}} {{HouseNr}}", - country: "{{Country}}", postalCode: "{{ZIP}}", + city: "{{City}}", + country: "{{Country}}", }, }; From 0c762230ff5ed7053afbd8a3651cee7dcc60450d Mon Sep 17 00:00:00 2001 From: Paul Rill Date: Mon, 11 Mar 2024 08:26:23 +0100 Subject: [PATCH 4/4] test: fixed a broken test --- test/Batch.spec.ts | 2 +- test/PrintOne.spec.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/Batch.spec.ts b/test/Batch.spec.ts index 04b1d8c..2fe3087 100644 --- a/test/Batch.spec.ts +++ b/test/Batch.spec.ts @@ -182,7 +182,7 @@ describe("getCsvOrder", function () { expect(csvOrder.recipientMapping).toEqual(mapping.recipient); expect(csvOrder.templateId).toEqual(template.id); expect(csvOrder.mergeVariableMapping).toEqual(mapping.mergeVariables); - expect(csvOrder.billingId).toEqual(undefined); + expect(csvOrder.billingId).toBeOneOf([undefined, expect.any(String)]); expect(csvOrder.finish).toEqual(expect.any(String)); expect(csvOrder.format).toEqual(expect.any(String)); expect(csvOrder.isBillable).toEqual(expect.any(Boolean)); diff --git a/test/PrintOne.spec.ts b/test/PrintOne.spec.ts index e273550..78fe30c 100644 --- a/test/PrintOne.spec.ts +++ b/test/PrintOne.spec.ts @@ -670,11 +670,11 @@ describe("createCsvOrder", function () { let file: ArrayBuffer = null as unknown as ArrayBuffer; const mapping: CreateCsvOrder["mapping"] = { recipient: { - city: "{{City}}", name: "{{FirstName}} {{LastName}}", address: "{{Street}} {{HouseNr}}", - country: "{{Country}}", postalCode: "{{ZIP}}", + city: "{{City}}", + country: "{{Country}}", }, }; @@ -721,7 +721,7 @@ describe("createCsvOrder", function () { expect(csvOrder.recipientMapping).toEqual(mapping.recipient); expect(csvOrder.templateId).toEqual(template.id); expect(csvOrder.mergeVariableMapping).toEqual(mapping.mergeVariables); - expect(csvOrder.billingId).toEqual(undefined); + expect(csvOrder.billingId).toBeOneOf([undefined, expect.any(String)]); expect(csvOrder.finish).toEqual(expect.any(String)); expect(csvOrder.format).toEqual(expect.any(String)); expect(csvOrder.isBillable).toEqual(expect.any(Boolean)); @@ -845,7 +845,7 @@ describe("getCsvOrder", function () { expect(csvOrder.recipientMapping).toEqual(mapping.recipient); expect(csvOrder.templateId).toEqual(template.id); expect(csvOrder.mergeVariableMapping).toEqual(mapping.mergeVariables); - expect(csvOrder.billingId).toEqual(undefined); + expect(csvOrder.billingId).toBeOneOf([undefined, expect.any(String)]); expect(csvOrder.finish).toEqual(expect.any(String)); expect(csvOrder.format).toEqual(expect.any(String)); expect(csvOrder.isBillable).toEqual(expect.any(Boolean));