diff --git a/integration-tests/api/__tests__/admin/draft-order.js b/integration-tests/api/__tests__/admin/draft-order.js index 7c67cb118e..5dd774482f 100644 --- a/integration-tests/api/__tests__/admin/draft-order.js +++ b/integration-tests/api/__tests__/admin/draft-order.js @@ -341,4 +341,68 @@ describe("/admin/draft-orders", () => { expect(response.data.count).toEqual(0); }); }); + + describe("DELETE /admin/draft-orders/:id", () => { + beforeEach(async () => { + try { + await adminSeeder(dbConnection); + await draftOrderSeeder(dbConnection); + } catch (err) { + console.log(err); + throw err; + } + }); + + afterEach(async () => { + const manager = dbConnection.manager; + await manager.query(`DELETE FROM "line_item"`); + await manager.query(`DELETE FROM "money_amount"`); + await manager.query(`DELETE FROM "product_variant"`); + await manager.query(`DELETE FROM "product"`); + await manager.query(`DELETE FROM "shipping_method"`); + await manager.query(`DELETE FROM "shipping_option"`); + await manager.query(`DELETE FROM "discount"`); + await manager.query(`DELETE FROM "payment_provider"`); + await manager.query(`DELETE FROM "payment_session"`); + await manager.query(`UPDATE "payment" SET order_id=NULL`); + await manager.query(`DELETE FROM "order"`); + await manager.query(`UPDATE "draft_order" SET order_id=NULL`); + await manager.query(`DELETE FROM "draft_order"`); + await manager.query(`DELETE FROM "cart"`); + await manager.query(`DELETE FROM "payment"`); + await manager.query(`DELETE FROM "customer"`); + await manager.query(`DELETE FROM "address"`); + + await manager.query( + `UPDATE "country" SET region_id=NULL WHERE iso_2 = 'us'` + ); + await manager.query( + `UPDATE "country" SET region_id=NULL WHERE iso_2 = 'de'` + ); + await manager.query(`DELETE FROM "region"`); + await manager.query(`DELETE FROM "user"`); + }); + + it("lists draft orders", async () => { + const api = useApi(); + + const response = await api + .delete("/admin/draft-orders/test-draft-order", { + headers: { + Authorization: "Bearer test_token", + }, + }) + .catch((err) => { + console.log(err); + }); + + expect(response.status).toEqual(200); + + expect(response.data).toEqual({ + id: "test-draft-order", + object: "draft-order", + deleted: true, + }); + }); + }); }); diff --git a/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.js b/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.js index 879a0be64d..1ec2e6261d 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.js +++ b/packages/medusa/src/api/routes/admin/draft-orders/create-draft-order.js @@ -40,7 +40,7 @@ export default async (req, res) => { .allow(0) .optional(), }) - .required(), + .optional(), metadata: Validator.object().optional(), requires_shipping: Validator.boolean().default(true), }) diff --git a/packages/medusa/src/api/routes/admin/draft-orders/delete-draft-order.js b/packages/medusa/src/api/routes/admin/draft-orders/delete-draft-order.js new file mode 100644 index 0000000000..f668ebf893 --- /dev/null +++ b/packages/medusa/src/api/routes/admin/draft-orders/delete-draft-order.js @@ -0,0 +1,15 @@ +export default async (req, res) => { + const { id } = req.params + + try { + const draftOrderService = req.scope.resolve("draftOrderService") + await draftOrderService.delete(id) + res.json({ + id, + object: "draft-order", + deleted: true, + }) + } catch (err) { + throw err + } +} diff --git a/packages/medusa/src/api/routes/admin/draft-orders/index.js b/packages/medusa/src/api/routes/admin/draft-orders/index.js index 7c3e2f51c3..1e6d3a70f5 100644 --- a/packages/medusa/src/api/routes/admin/draft-orders/index.js +++ b/packages/medusa/src/api/routes/admin/draft-orders/index.js @@ -14,6 +14,11 @@ export default app => { route.post("/:id", middlewares.wrap(require("./update-draft-order").default)) + route.delete( + "/:id", + middlewares.wrap(require("./delete-draft-order").default) + ) + route.delete( "/:id/line-items/:line_id", middlewares.wrap(require("./delete-line-item").default) diff --git a/packages/medusa/src/api/routes/admin/store/update-store.js b/packages/medusa/src/api/routes/admin/store/update-store.js index ce63b7fbc9..d1cc4983f4 100644 --- a/packages/medusa/src/api/routes/admin/store/update-store.js +++ b/packages/medusa/src/api/routes/admin/store/update-store.js @@ -4,6 +4,7 @@ export default async (req, res) => { const schema = Validator.object().keys({ name: Validator.string(), swap_link_template: Validator.string(), + payment_link_template: Validator.string(), default_currency_code: Validator.string(), currencies: Validator.array().items(Validator.string()), }) diff --git a/packages/medusa/src/migrations/1613384784316-draft_orders.ts b/packages/medusa/src/migrations/1613384784316-draft_orders.ts index 8bb3a13576..cbc04504fc 100644 --- a/packages/medusa/src/migrations/1613384784316-draft_orders.ts +++ b/packages/medusa/src/migrations/1613384784316-draft_orders.ts @@ -21,6 +21,7 @@ export class draftOrders1613384784316 implements MigrationInterface { await queryRunner.query(`ALTER TABLE "draft_order" ADD CONSTRAINT "FK_5bd11d0e2a9628128e2c26fd0a6" FOREIGN KEY ("cart_id") REFERENCES "cart"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); await queryRunner.query(`ALTER TABLE "draft_order" ADD CONSTRAINT "FK_8f6dd6c49202f1466ebf21e77da" FOREIGN KEY ("order_id") REFERENCES "order"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); await queryRunner.query(`ALTER TABLE "order" ADD CONSTRAINT "FK_727b872f86c7378474a8fa46147" FOREIGN KEY ("draft_order_id") REFERENCES "draft_order"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE "store" ADD "payment_link_template" character varying`); } public async down(queryRunner: QueryRunner): Promise { @@ -41,6 +42,7 @@ export class draftOrders1613384784316 implements MigrationInterface { await queryRunner.query(`DROP INDEX "IDX_e87cc617a22ef4edce5601edab"`); await queryRunner.query(`DROP TABLE "draft_order"`); await queryRunner.query(`DROP TYPE "draft_order_status_enum"`); + await queryRunner.query(`ALTER TABLE "store" DROP COLUMN "payment_link_template"`); } } diff --git a/packages/medusa/src/migrations/1613634008478-payment_link_template.ts b/packages/medusa/src/migrations/1613634008478-payment_link_template.ts new file mode 100644 index 0000000000..60858cc3fd --- /dev/null +++ b/packages/medusa/src/migrations/1613634008478-payment_link_template.ts @@ -0,0 +1,14 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class paymentLinkTemplate1613634008478 implements MigrationInterface { + name = 'paymentLinkTemplate1613634008478' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "store" ADD "payment_link_template" character varying`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "store" DROP COLUMN "payment_link_template"`); + } + +} diff --git a/packages/medusa/src/models/draft-order.ts b/packages/medusa/src/models/draft-order.ts index 5e63751cfd..031a7f8fc7 100644 --- a/packages/medusa/src/models/draft-order.ts +++ b/packages/medusa/src/models/draft-order.ts @@ -49,7 +49,7 @@ export class DraftOrder { @Column({ nullable: true }) cart_id: string - @OneToOne(() => Cart) + @OneToOne(() => Cart, { onDelete: "CASCADE" }) @JoinColumn({ name: "cart_id" }) cart: Cart diff --git a/packages/medusa/src/models/store.ts b/packages/medusa/src/models/store.ts index 1b03e7e5e1..ea12282b46 100644 --- a/packages/medusa/src/models/store.ts +++ b/packages/medusa/src/models/store.ts @@ -50,6 +50,9 @@ export class Store { @Column({ nullable: true }) swap_link_template: string + @Column({ nullable: true }) + payment_link_template: string + @CreateDateColumn({ type: "timestamptz" }) created_at: Date diff --git a/packages/medusa/src/services/draft-order.js b/packages/medusa/src/services/draft-order.js index 859fcecaeb..55245b2280 100644 --- a/packages/medusa/src/services/draft-order.js +++ b/packages/medusa/src/services/draft-order.js @@ -229,6 +229,29 @@ class DraftOrderService extends BaseService { return draftOrder } + /** + * Deletes draft order idempotently. + * @param {string} draftOrderId - id of draft order to delete + * @return {Promise} empty promise + */ + async delete(draftOrderId) { + return this.atomicPhase_(async manager => { + const draftOrderRepo = manager.getCustomRepository( + this.draftOrderRepository_ + ) + + const draftOrder = await draftOrderRepo.findOne({ + where: { id: draftOrderId }, + }) + + if (!draftOrder) return Promise.resolve() + + await draftOrderRepo.remove(draftOrder) + + return Promise.resolve() + }) + } + async listAndCount( selector, config = { skip: 0, take: 50, order: { created_at: "DESC" } } @@ -503,12 +526,25 @@ class DraftOrderService extends BaseService { draftOrder.status = "completed" draftOrder.order_id = result.id - console.log(draftOrder) await draftOrderRepo.save(draftOrder) return result }) } + + async registerCartCompletion(doId, orderId) { + return this.atomicPhase_(async manager => { + const draftOrderRepo = manager.getCustomRepository( + this.draftOrderRepository_ + ) + const draftOrder = await this.retrieve(doId) + + draftOrder.status = "completed" + draftOrder.order_id = orderId + + await draftOrderRepo.save(draftOrder) + }) + } } export default DraftOrderService diff --git a/packages/medusa/src/services/payment-provider.js b/packages/medusa/src/services/payment-provider.js index 0d2fee1322..ba5dcce778 100644 --- a/packages/medusa/src/services/payment-provider.js +++ b/packages/medusa/src/services/payment-provider.js @@ -223,7 +223,14 @@ class PaymentProviderService extends BaseService { */ retrieveProvider(providerId) { try { - const provider = this.container_[`pp_${providerId}`] + let provider + if (providerId === "system") { + console.log(this.container_) + provider = this.container_[`systemPaymentProviderService`] + } else { + provider = this.container_[`pp_${providerId}`] + } + return provider } catch (err) { throw new MedusaError( diff --git a/packages/medusa/src/subscribers/order.js b/packages/medusa/src/subscribers/order.js index 2970d53eeb..fcca7579b0 100644 --- a/packages/medusa/src/subscribers/order.js +++ b/packages/medusa/src/subscribers/order.js @@ -6,6 +6,7 @@ class OrderSubscriber { giftCardService, totalsService, orderService, + draftOrderService, regionService, }) { this.manager_ = manager @@ -17,11 +18,15 @@ class OrderSubscriber { this.orderService_ = orderService + this.draftOrderService_ = draftOrderService + this.regionService_ = regionService this.eventBus_ = eventBusService this.eventBus_.subscribe("order.placed", this.handleOrderPlaced) + + this.eventBus_.subscribe("order.placed", this.updateDraftOrder) } handleOrderPlaced = async data => { @@ -54,6 +59,21 @@ class OrderSubscriber { }) ) } + + updateDraftOrder = async data => { + const order = await this.orderService_.retrieve(data.id) + + const draftOrder = await this.draftOrderService_.retrieveByCartId( + order.cart_id + ) + + if (draftOrder) { + await this.draftOrderService_.registerCartCompletion( + draftOrder.id, + order.id + ) + } + } } export default OrderSubscriber