From 339a946f389033c21e05338f9dbf07d88e140533 Mon Sep 17 00:00:00 2001 From: "Carlos R. L. Rodrigues" <37986729+carlos-r-l-rodrigues@users.noreply.github.com> Date: Thu, 15 Feb 2024 10:26:00 -0300 Subject: [PATCH] feat(order): module foundation (#6399) What: Initial Order module foundation. Basic models and methods to manage entites like in Cart Module --- .changeset/late-pillows-move.md | 7 + packages/fulfillment/src/models/address.ts | 4 +- .../src/models/fulfillment-item.ts | 10 +- .../src/models/fulfillment-label.ts | 6 +- .../fulfillment/src/models/fulfillment.ts | 14 +- .../fulfillment/src/models/fullfilment-set.ts | 6 +- packages/fulfillment/src/models/geo-zone.ts | 12 +- .../src/models/service-provider.ts | 4 +- .../fulfillment/src/models/service-zone.ts | 8 +- .../src/models/shipping-option-rule.ts | 4 +- .../src/models/shipping-option-type.ts | 6 +- .../fulfillment/src/models/shipping-option.ts | 22 +- .../src/models/shipping-profile.ts | 4 +- packages/medusa/src/models/order.ts | 2 +- packages/modules-sdk/src/definitions.ts | 16 + packages/order/.gitignore | 6 + packages/order/README.md | 1 + .../integration-tests/__fixtures__/index.ts | 1 + .../integration-tests/__tests__/index.ts | 5 + packages/order/integration-tests/setup-env.js | 6 + packages/order/integration-tests/setup.js | 3 + .../order/integration-tests/utils/database.ts | 13 + .../utils/get-init-module-config.ts | 33 + .../order/integration-tests/utils/index.ts | 2 + packages/order/jest.config.js | 22 + packages/order/mikro-orm.config.dev.ts | 12 + packages/order/package.json | 61 + packages/order/src/index.ts | 14 + packages/order/src/joiner-config.ts | 26 + packages/order/src/models/address.ts | 90 ++ packages/order/src/models/adjustment-line.ts | 52 + packages/order/src/models/index.ts | 8 + .../order/src/models/line-item-adjustment.ts | 38 + .../order/src/models/line-item-tax-line.ts | 34 + packages/order/src/models/line-item.ts | 192 +++ packages/order/src/models/order.ts | 168 +++ .../src/models/shipping-method-adjustment.ts | 35 + .../src/models/shipping-method-tax-line.ts | 35 + packages/order/src/models/shipping-method.ts | 134 ++ packages/order/src/models/tax-line.ts | 48 + packages/order/src/module-definition.ts | 44 + packages/order/src/repositories/index.ts | 1 + packages/order/src/scripts/bin/run-seed.ts | 29 + packages/order/src/services/__tests__/noop.ts | 5 + packages/order/src/services/index.ts | 1 + .../src/services/order-module-service.ts | 1280 +++++++++++++++++ .../src/types/UpdateOrderShippingMethodDTO.ts | 8 + packages/order/src/types/address.ts | 20 + packages/order/src/types/index.ts | 15 + .../order/src/types/line-item-adjustment.ts | 15 + .../order/src/types/line-item-tax-line.ts | 9 + packages/order/src/types/line-item.ts | 39 + packages/order/src/types/order.ts | 33 + .../src/types/shipping-method-adjustment.ts | 19 + .../src/types/shipping-method-tax-line.ts | 11 + packages/order/src/types/shipping-method.ts | 15 + packages/order/src/types/tax-line.ts | 18 + packages/order/tsconfig.json | 37 + packages/order/tsconfig.spec.json | 8 + packages/types/src/bundles.ts | 2 +- packages/types/src/index.ts | 4 +- packages/types/src/order/common.ts | 570 ++++++++ packages/types/src/order/index.ts | 3 + packages/types/src/order/mutations.ts | 241 ++++ packages/types/src/order/service.ts | 328 +++++ packages/types/src/totals/big-number.ts | 6 +- packages/user/src/models/invite.ts | 16 +- packages/user/src/models/user.ts | 17 +- packages/utils/src/bundles.ts | 1 + .../__tests__/create-psql-index-helper.ts | 25 +- .../src/common/create-psql-index-helper.ts | 33 +- packages/utils/src/index.ts | 1 + packages/utils/src/order/index.ts | 1 + packages/utils/src/order/status.ts | 31 + packages/utils/src/totals/big-number.ts | 10 +- packages/utils/src/totals/to-big-number-js.ts | 4 +- yarn.lock | 27 + 77 files changed, 3998 insertions(+), 93 deletions(-) create mode 100644 .changeset/late-pillows-move.md create mode 100644 packages/order/.gitignore create mode 100644 packages/order/README.md create mode 100644 packages/order/integration-tests/__fixtures__/index.ts create mode 100644 packages/order/integration-tests/__tests__/index.ts create mode 100644 packages/order/integration-tests/setup-env.js create mode 100644 packages/order/integration-tests/setup.js create mode 100644 packages/order/integration-tests/utils/database.ts create mode 100644 packages/order/integration-tests/utils/get-init-module-config.ts create mode 100644 packages/order/integration-tests/utils/index.ts create mode 100644 packages/order/jest.config.js create mode 100644 packages/order/mikro-orm.config.dev.ts create mode 100644 packages/order/package.json create mode 100644 packages/order/src/index.ts create mode 100644 packages/order/src/joiner-config.ts create mode 100644 packages/order/src/models/address.ts create mode 100644 packages/order/src/models/adjustment-line.ts create mode 100644 packages/order/src/models/index.ts create mode 100644 packages/order/src/models/line-item-adjustment.ts create mode 100644 packages/order/src/models/line-item-tax-line.ts create mode 100644 packages/order/src/models/line-item.ts create mode 100644 packages/order/src/models/order.ts create mode 100644 packages/order/src/models/shipping-method-adjustment.ts create mode 100644 packages/order/src/models/shipping-method-tax-line.ts create mode 100644 packages/order/src/models/shipping-method.ts create mode 100644 packages/order/src/models/tax-line.ts create mode 100644 packages/order/src/module-definition.ts create mode 100644 packages/order/src/repositories/index.ts create mode 100644 packages/order/src/scripts/bin/run-seed.ts create mode 100644 packages/order/src/services/__tests__/noop.ts create mode 100644 packages/order/src/services/index.ts create mode 100644 packages/order/src/services/order-module-service.ts create mode 100644 packages/order/src/types/UpdateOrderShippingMethodDTO.ts create mode 100644 packages/order/src/types/address.ts create mode 100644 packages/order/src/types/index.ts create mode 100644 packages/order/src/types/line-item-adjustment.ts create mode 100644 packages/order/src/types/line-item-tax-line.ts create mode 100644 packages/order/src/types/line-item.ts create mode 100644 packages/order/src/types/order.ts create mode 100644 packages/order/src/types/shipping-method-adjustment.ts create mode 100644 packages/order/src/types/shipping-method-tax-line.ts create mode 100644 packages/order/src/types/shipping-method.ts create mode 100644 packages/order/src/types/tax-line.ts create mode 100644 packages/order/tsconfig.json create mode 100644 packages/order/tsconfig.spec.json create mode 100644 packages/types/src/order/common.ts create mode 100644 packages/types/src/order/index.ts create mode 100644 packages/types/src/order/mutations.ts create mode 100644 packages/types/src/order/service.ts create mode 100644 packages/utils/src/order/index.ts create mode 100644 packages/utils/src/order/status.ts diff --git a/.changeset/late-pillows-move.md b/.changeset/late-pillows-move.md new file mode 100644 index 0000000000..0867b0c7e7 --- /dev/null +++ b/.changeset/late-pillows-move.md @@ -0,0 +1,7 @@ +--- +"@medusajs/modules-sdk": patch +"@medusajs/types": patch +"@medusajs/utils": patch +--- + +Initial Order module implementation diff --git a/packages/fulfillment/src/models/address.ts b/packages/fulfillment/src/models/address.ts index 80a64345e1..1bb2a1dcbb 100644 --- a/packages/fulfillment/src/models/address.ts +++ b/packages/fulfillment/src/models/address.ts @@ -21,7 +21,7 @@ const fulfillmentIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment_address", columns: "fulfillment_id", where: "deleted_at IS NULL", -}) +}).expression const fulfillmentDeletedAtIndexName = "IDX_fulfillment_address_deleted_at" const fulfillmentDeletedAtIndexStatement = createPsqlIndexStatementHelper({ @@ -29,7 +29,7 @@ const fulfillmentDeletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment_address", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression @Entity({ tableName: "fulfillment_address" }) export default class Address { diff --git a/packages/fulfillment/src/models/fulfillment-item.ts b/packages/fulfillment/src/models/fulfillment-item.ts index 4baaf05380..b59a06cd9f 100644 --- a/packages/fulfillment/src/models/fulfillment-item.ts +++ b/packages/fulfillment/src/models/fulfillment-item.ts @@ -4,6 +4,7 @@ import { generateEntityId, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Entity, @@ -15,7 +16,6 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" import Fulfillment from "./fulfillment" type FulfillmentItemOptionalProps = DAL.SoftDeletableEntityDateColumns @@ -26,7 +26,7 @@ const fulfillmentIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment_item", columns: "fulfillment_id", where: "deleted_at IS NULL", -}) +}).expression const lineItemIndexName = "IDX_fulfillment_item_line_item_id" const lineItemIdIndexStatement = createPsqlIndexStatementHelper({ @@ -34,7 +34,7 @@ const lineItemIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment_item", columns: "line_item_id", where: "deleted_at IS NULL", -}) +}).expression const inventoryItemIndexName = "IDX_fulfillment_item_inventory_item_id" const inventoryItemIdIndexStatement = createPsqlIndexStatementHelper({ @@ -42,7 +42,7 @@ const inventoryItemIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment_item", columns: "inventory_item_id", where: "deleted_at IS NULL", -}) +}).expression const fulfillmentItemDeletedAtIndexName = "IDX_fulfillment_item_deleted_at" const fulfillmentItemDeletedAtIndexStatement = createPsqlIndexStatementHelper({ @@ -50,7 +50,7 @@ const fulfillmentItemDeletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment_item", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/fulfillment/src/models/fulfillment-label.ts b/packages/fulfillment/src/models/fulfillment-label.ts index f770b5cf5c..ae35ade0a1 100644 --- a/packages/fulfillment/src/models/fulfillment-label.ts +++ b/packages/fulfillment/src/models/fulfillment-label.ts @@ -4,6 +4,7 @@ import { generateEntityId, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Entity, @@ -15,7 +16,6 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" import Fulfillment from "./fulfillment" type FulfillmentLabelOptionalProps = DAL.SoftDeletableEntityDateColumns @@ -26,7 +26,7 @@ const fulfillmentIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment_label", columns: "fulfillment_id", where: "deleted_at IS NULL", -}) +}).expression const deletedAtIndexName = "IDX_fulfillment_label_deleted_at" const deletedAtIndexStatement = createPsqlIndexStatementHelper({ @@ -34,7 +34,7 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment_label", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/fulfillment/src/models/fulfillment.ts b/packages/fulfillment/src/models/fulfillment.ts index 4f3731e84c..f2cbca71a1 100644 --- a/packages/fulfillment/src/models/fulfillment.ts +++ b/packages/fulfillment/src/models/fulfillment.ts @@ -4,6 +4,7 @@ import { generateEntityId, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Collection, @@ -17,12 +18,11 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" -import ShippingOption from "./shipping-option" -import ServiceProvider from "./service-provider" import Address from "./address" import FulfillmentItem from "./fulfillment-item" import FulfillmentLabel from "./fulfillment-label" +import ServiceProvider from "./service-provider" +import ShippingOption from "./shipping-option" type FulfillmentOptionalProps = DAL.SoftDeletableEntityDateColumns @@ -32,7 +32,7 @@ const fulfillmentDeletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression const fulfillmentProviderIdIndexName = "IDX_fulfillment_provider_id" const fulfillmentProviderIdIndexStatement = createPsqlIndexStatementHelper({ @@ -40,7 +40,7 @@ const fulfillmentProviderIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment", columns: "provider_id", where: "deleted_at IS NULL", -}) +}).expression const fulfillmentLocationIdIndexName = "IDX_fulfillment_location_id" const fulfillmentLocationIdIndexStatement = createPsqlIndexStatementHelper({ @@ -48,7 +48,7 @@ const fulfillmentLocationIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment", columns: "location_id", where: "deleted_at IS NULL", -}) +}).expression const fulfillmentShippingOptionIdIndexName = "IDX_fulfillment_shipping_option_id" @@ -58,7 +58,7 @@ const fulfillmentShippingOptionIdIndexStatement = tableName: "fulfillment", columns: "shipping_option_id", where: "deleted_at IS NULL", - }) + }).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/fulfillment/src/models/fullfilment-set.ts b/packages/fulfillment/src/models/fullfilment-set.ts index 38c056ea11..55a4623565 100644 --- a/packages/fulfillment/src/models/fullfilment-set.ts +++ b/packages/fulfillment/src/models/fullfilment-set.ts @@ -4,6 +4,7 @@ import { generateEntityId, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Cascade, @@ -17,7 +18,6 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" import ServiceZone from "./service-zone" type FulfillmentSetOptionalProps = DAL.SoftDeletableEntityDateColumns @@ -28,7 +28,7 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "fulfillment_set", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression const nameIndexName = "IDX_fulfillment_set_name_unique" const nameIndexStatement = createPsqlIndexStatementHelper({ @@ -37,7 +37,7 @@ const nameIndexStatement = createPsqlIndexStatementHelper({ columns: "name", unique: true, where: "deleted_at IS NULL", -}) +}).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/fulfillment/src/models/geo-zone.ts b/packages/fulfillment/src/models/geo-zone.ts index 3104a4c4fb..85d2f7ba72 100644 --- a/packages/fulfillment/src/models/geo-zone.ts +++ b/packages/fulfillment/src/models/geo-zone.ts @@ -5,6 +5,7 @@ import { GeoZoneType, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Entity, @@ -17,7 +18,6 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" import ServiceZone from "./service-zone" type GeoZoneOptionalProps = DAL.SoftDeletableEntityDateColumns @@ -28,7 +28,7 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "geo_zone", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression const countryCodeIndexName = "IDX_geo_zone_country_code" const countryCodeIndexStatement = createPsqlIndexStatementHelper({ @@ -36,7 +36,7 @@ const countryCodeIndexStatement = createPsqlIndexStatementHelper({ tableName: "geo_zone", columns: "country_code", where: "deleted_at IS NULL", -}) +}).expression const provinceCodeIndexName = "IDX_geo_zone_province_code" const provinceCodeIndexStatement = createPsqlIndexStatementHelper({ @@ -44,7 +44,7 @@ const provinceCodeIndexStatement = createPsqlIndexStatementHelper({ tableName: "geo_zone", columns: "province_code", where: "deleted_at IS NULL AND province_code IS NOT NULL", -}) +}).expression const cityIndexName = "IDX_geo_zone_city" const cityIndexStatement = createPsqlIndexStatementHelper({ @@ -52,7 +52,7 @@ const cityIndexStatement = createPsqlIndexStatementHelper({ tableName: "geo_zone", columns: "city", where: "deleted_at IS NULL AND city IS NOT NULL", -}) +}).expression const serviceZoneIdIndexName = "IDX_geo_zone_service_zone_id" const serviceZoneIdStatement = createPsqlIndexStatementHelper({ @@ -60,7 +60,7 @@ const serviceZoneIdStatement = createPsqlIndexStatementHelper({ tableName: "geo_zone", columns: "service_zone_id", where: "deleted_at IS NULL", -}) +}).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/fulfillment/src/models/service-provider.ts b/packages/fulfillment/src/models/service-provider.ts index 414418ee27..4855c60c4f 100644 --- a/packages/fulfillment/src/models/service-provider.ts +++ b/packages/fulfillment/src/models/service-provider.ts @@ -4,6 +4,7 @@ import { generateEntityId, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Collection, @@ -16,7 +17,6 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" import ShippingOption from "./shipping-option" type ServiceProviderOptionalProps = DAL.SoftDeletableEntityDateColumns @@ -27,7 +27,7 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "service_provider", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/fulfillment/src/models/service-zone.ts b/packages/fulfillment/src/models/service-zone.ts index 5ca0fe6a25..fb5d511404 100644 --- a/packages/fulfillment/src/models/service-zone.ts +++ b/packages/fulfillment/src/models/service-zone.ts @@ -4,6 +4,7 @@ import { generateEntityId, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Cascade, @@ -18,7 +19,6 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" import FulfillmentSet from "./fullfilment-set" import GeoZone from "./geo-zone" import ShippingOption from "./shipping-option" @@ -31,7 +31,7 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "service_zone", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression const nameIndexName = "IDX_service_zone_name_unique" const nameIndexStatement = createPsqlIndexStatementHelper({ @@ -40,7 +40,7 @@ const nameIndexStatement = createPsqlIndexStatementHelper({ columns: "name", unique: true, where: "deleted_at IS NULL", -}) +}).expression const fulfillmentSetIdIndexName = "IDX_service_zone_fulfillment_set_id" const fulfillmentSetIdIndexStatement = createPsqlIndexStatementHelper({ @@ -48,7 +48,7 @@ const fulfillmentSetIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "service_zone", columns: "fulfillment_set_id", where: "deleted_at IS NULL", -}) +}).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/fulfillment/src/models/shipping-option-rule.ts b/packages/fulfillment/src/models/shipping-option-rule.ts index 8cc79c494d..b4bc049b4e 100644 --- a/packages/fulfillment/src/models/shipping-option-rule.ts +++ b/packages/fulfillment/src/models/shipping-option-rule.ts @@ -4,6 +4,7 @@ import { generateEntityId, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Entity, @@ -15,7 +16,6 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" import ShippingOption from "./shipping-option" type ShippingOptionRuleOptionalProps = DAL.SoftDeletableEntityDateColumns @@ -29,7 +29,7 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "shipping_option_rule", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/fulfillment/src/models/shipping-option-type.ts b/packages/fulfillment/src/models/shipping-option-type.ts index bed46b6ffe..80858b4511 100644 --- a/packages/fulfillment/src/models/shipping-option-type.ts +++ b/packages/fulfillment/src/models/shipping-option-type.ts @@ -4,6 +4,7 @@ import { generateEntityId, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Entity, @@ -15,7 +16,6 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" import ShippingOption from "./shipping-option" type ShippingOptionTypeOptionalProps = DAL.SoftDeletableEntityDateColumns @@ -26,7 +26,7 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "shipping_option_type", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression const shippingOptionIdIndexName = "IDX_shipping_option_type_shipping_option_id" const shippingOptionIdIndexStatement = createPsqlIndexStatementHelper({ @@ -34,7 +34,7 @@ const shippingOptionIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "shipping_option_type", columns: "shipping_option_id", where: "deleted_at IS NULL", -}) +}).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/fulfillment/src/models/shipping-option.ts b/packages/fulfillment/src/models/shipping-option.ts index 0e913d05b9..1c9d8ea267 100644 --- a/packages/fulfillment/src/models/shipping-option.ts +++ b/packages/fulfillment/src/models/shipping-option.ts @@ -5,6 +5,7 @@ import { ShippingOptionPriceType, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Collection, @@ -20,13 +21,12 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" -import ServiceZone from "./service-zone" -import ShippingProfile from "./shipping-profile" -import ServiceProvider from "./service-provider" -import ShippingOptionType from "./shipping-option-type" -import ShippingOptionRule from "./shipping-option-rule" import Fulfillment from "./fulfillment" +import ServiceProvider from "./service-provider" +import ServiceZone from "./service-zone" +import ShippingOptionRule from "./shipping-option-rule" +import ShippingOptionType from "./shipping-option-type" +import ShippingProfile from "./shipping-profile" type ShippingOptionOptionalProps = DAL.SoftDeletableEntityDateColumns @@ -36,7 +36,7 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "shipping_option", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression const serviceZoneIdIndexName = "IDX_shipping_option_service_zone_id" const serviceZoneIdIndexStatement = createPsqlIndexStatementHelper({ @@ -44,7 +44,7 @@ const serviceZoneIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "shipping_option", columns: "service_zone_id", where: "deleted_at IS NULL", -}) +}).expression const shippingProfileIdIndexName = "IDX_shipping_option_shipping_profile_id" const shippingProfileIdIndexStatement = createPsqlIndexStatementHelper({ @@ -52,7 +52,7 @@ const shippingProfileIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "shipping_option", columns: "shipping_profile_id", where: "deleted_at IS NULL", -}) +}).expression const serviceProviderIdIndexName = "IDX_shipping_option_service_provider_id" const serviceProviderIdIndexStatement = createPsqlIndexStatementHelper({ @@ -60,7 +60,7 @@ const serviceProviderIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "shipping_option", columns: "service_provider_id", where: "deleted_at IS NULL", -}) +}).expression const shippingOptionTypeIdIndexName = "IDX_shipping_option_shipping_option_type_id" @@ -69,7 +69,7 @@ const shippingOptionTypeIdIndexStatement = createPsqlIndexStatementHelper({ tableName: "shipping_option", columns: "shipping_option_type_id", where: "deleted_at IS NULL", -}) +}).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/fulfillment/src/models/shipping-profile.ts b/packages/fulfillment/src/models/shipping-profile.ts index f2371ec575..b8a359e64b 100644 --- a/packages/fulfillment/src/models/shipping-profile.ts +++ b/packages/fulfillment/src/models/shipping-profile.ts @@ -4,6 +4,7 @@ import { generateEntityId, } from "@medusajs/utils" +import { DAL } from "@medusajs/types" import { BeforeCreate, Collection, @@ -16,7 +17,6 @@ import { PrimaryKey, Property, } from "@mikro-orm/core" -import { DAL } from "@medusajs/types" import ShippingOption from "./shipping-option" type ShippingProfileOptionalProps = DAL.SoftDeletableEntityDateColumns @@ -27,7 +27,7 @@ const deletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "shipping_profile", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression @Entity() @Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) diff --git a/packages/medusa/src/models/order.ts b/packages/medusa/src/models/order.ts index b2af49dbe7..476e207780 100644 --- a/packages/medusa/src/models/order.ts +++ b/packages/medusa/src/models/order.ts @@ -19,6 +19,7 @@ import { FeatureFlagDecorators, } from "../utils/feature-flag-decorators" +import { MedusaV2Flag } from "@medusajs/utils" import { BaseEntity } from "../interfaces/models/base-entity" import { generateEntityId } from "../utils/generate-entity-id" import { manualAutoIncrement } from "../utils/manual-auto-increment" @@ -41,7 +42,6 @@ import { Return } from "./return" import { SalesChannel } from "./sales-channel" import { ShippingMethod } from "./shipping-method" import { Swap } from "./swap" -import { MedusaV2Flag } from "@medusajs/utils" /** * @enum diff --git a/packages/modules-sdk/src/definitions.ts b/packages/modules-sdk/src/definitions.ts index aeb8d228d0..b3aaed2c9d 100644 --- a/packages/modules-sdk/src/definitions.ts +++ b/packages/modules-sdk/src/definitions.ts @@ -24,6 +24,7 @@ export enum Modules { USER = "user", WORKFLOW_ENGINE = "workflows", REGION = "region", + ORDER = "order", } export enum ModuleRegistrationName { @@ -43,6 +44,7 @@ export enum ModuleRegistrationName { USER = "userModuleService", WORKFLOW_ENGINE = "workflowsModuleService", REGION = "regionModuleService", + ORDER = "orderModuleService", } export const MODULE_PACKAGE_NAMES = { @@ -63,6 +65,7 @@ export const MODULE_PACKAGE_NAMES = { [Modules.USER]: "@medusajs/user", [Modules.WORKFLOW_ENGINE]: "@medusajs/workflow-engine-inmemory", [Modules.REGION]: "@medusajs/region", + [Modules.ORDER]: "@medusajs/order", } export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } = @@ -276,6 +279,19 @@ export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } = resources: MODULE_RESOURCE_TYPE.SHARED, }, }, + [Modules.ORDER]: { + key: Modules.ORDER, + registrationName: ModuleRegistrationName.ORDER, + defaultPackage: false, + label: upperCaseFirst(ModuleRegistrationName.ORDER), + isRequired: false, + isQueryable: true, + dependencies: ["logger", "eventBusService"], + defaultModuleDeclaration: { + scope: MODULE_SCOPE.INTERNAL, + resources: MODULE_RESOURCE_TYPE.SHARED, + }, + }, } export const MODULE_DEFINITIONS: ModuleDefinition[] = diff --git a/packages/order/.gitignore b/packages/order/.gitignore new file mode 100644 index 0000000000..874c6c69d3 --- /dev/null +++ b/packages/order/.gitignore @@ -0,0 +1,6 @@ +/dist +node_modules +.DS_store +.env* +.env +*.sql diff --git a/packages/order/README.md b/packages/order/README.md new file mode 100644 index 0000000000..67348c9104 --- /dev/null +++ b/packages/order/README.md @@ -0,0 +1 @@ +# Order Module diff --git a/packages/order/integration-tests/__fixtures__/index.ts b/packages/order/integration-tests/__fixtures__/index.ts new file mode 100644 index 0000000000..172f1ae6a4 --- /dev/null +++ b/packages/order/integration-tests/__fixtures__/index.ts @@ -0,0 +1 @@ +// noop diff --git a/packages/order/integration-tests/__tests__/index.ts b/packages/order/integration-tests/__tests__/index.ts new file mode 100644 index 0000000000..333c84c1dd --- /dev/null +++ b/packages/order/integration-tests/__tests__/index.ts @@ -0,0 +1,5 @@ +describe("noop", function () { + it("should run", function () { + expect(true).toBe(true) + }) +}) diff --git a/packages/order/integration-tests/setup-env.js b/packages/order/integration-tests/setup-env.js new file mode 100644 index 0000000000..739649eae6 --- /dev/null +++ b/packages/order/integration-tests/setup-env.js @@ -0,0 +1,6 @@ +if (typeof process.env.DB_TEMP_NAME === "undefined") { + const tempName = parseInt(process.env.JEST_WORKER_ID || "1") + process.env.DB_TEMP_NAME = `medusa-order-integration-${tempName}` +} + +process.env.MEDUSA_ORDER_DB_SCHEMA = "public" diff --git a/packages/order/integration-tests/setup.js b/packages/order/integration-tests/setup.js new file mode 100644 index 0000000000..43f99aab4a --- /dev/null +++ b/packages/order/integration-tests/setup.js @@ -0,0 +1,3 @@ +import { JestUtils } from "medusa-test-utils" + +JestUtils.afterAllHookDropDatabase() diff --git a/packages/order/integration-tests/utils/database.ts b/packages/order/integration-tests/utils/database.ts new file mode 100644 index 0000000000..d1ba6a830c --- /dev/null +++ b/packages/order/integration-tests/utils/database.ts @@ -0,0 +1,13 @@ +import { TestDatabaseUtils } from "medusa-test-utils" + +import * as Models from "@models" + +const mikroOrmEntities = Models as unknown as any[] + +export const MikroOrmWrapper = TestDatabaseUtils.getMikroOrmWrapper( + mikroOrmEntities, + null, + process.env.MEDUSA_FULFILLMENT_DB_SCHEMA +) + +export const DB_URL = TestDatabaseUtils.getDatabaseURL() diff --git a/packages/order/integration-tests/utils/get-init-module-config.ts b/packages/order/integration-tests/utils/get-init-module-config.ts new file mode 100644 index 0000000000..f86e3e7b90 --- /dev/null +++ b/packages/order/integration-tests/utils/get-init-module-config.ts @@ -0,0 +1,33 @@ +import { Modules, ModulesDefinition } from "@medusajs/modules-sdk" + +import { DB_URL } from "./database" + +export function getInitModuleConfig() { + const moduleOptions = { + defaultAdapterOptions: { + database: { + clientUrl: DB_URL, + schema: process.env.MEDUSA_ORDER_DB_SCHEMA, + }, + }, + } + + const injectedDependencies = {} + + const modulesConfig_ = { + [Modules.ORDER]: { + definition: ModulesDefinition[Modules.ORDER], + options: moduleOptions, + }, + } + + return { + injectedDependencies, + modulesConfig: modulesConfig_, + databaseConfig: { + clientUrl: DB_URL, + schema: process.env.MEDUSA_ORDER_DB_SCHEMA, + }, + joinerConfig: [], + } +} diff --git a/packages/order/integration-tests/utils/index.ts b/packages/order/integration-tests/utils/index.ts new file mode 100644 index 0000000000..ba28fb5523 --- /dev/null +++ b/packages/order/integration-tests/utils/index.ts @@ -0,0 +1,2 @@ +export * from "./database" +export * from "./get-init-module-config" diff --git a/packages/order/jest.config.js b/packages/order/jest.config.js new file mode 100644 index 0000000000..456054fe8a --- /dev/null +++ b/packages/order/jest.config.js @@ -0,0 +1,22 @@ +module.exports = { + moduleNameMapper: { + "^@models": "/src/models", + "^@services": "/src/services", + "^@repositories": "/src/repositories", + "^@types": "/src/types", + }, + transform: { + "^.+\\.[jt]s?$": [ + "ts-jest", + { + tsConfig: "tsconfig.spec.json", + isolatedModules: true, + }, + ], + }, + testEnvironment: `node`, + moduleFileExtensions: [`js`, `ts`], + modulePathIgnorePatterns: ["dist/"], + setupFiles: ["/integration-tests/setup-env.js"], + setupFilesAfterEnv: ["/integration-tests/setup.js"], +} diff --git a/packages/order/mikro-orm.config.dev.ts b/packages/order/mikro-orm.config.dev.ts new file mode 100644 index 0000000000..963eb5e619 --- /dev/null +++ b/packages/order/mikro-orm.config.dev.ts @@ -0,0 +1,12 @@ +import { TSMigrationGenerator } from "@medusajs/utils" +import * as entities from "./src/models" + +module.exports = { + entities: Object.values(entities), + schema: "public", + clientUrl: "postgres://postgres@localhost/medusa-order", + type: "postgresql", + migrations: { + generator: TSMigrationGenerator, + }, +} diff --git a/packages/order/package.json b/packages/order/package.json new file mode 100644 index 0000000000..f8ed9e5eba --- /dev/null +++ b/packages/order/package.json @@ -0,0 +1,61 @@ +{ + "name": "@medusajs/order", + "version": "0.1.0", + "description": "Medusa Order module", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "engines": { + "node": ">=16" + }, + "bin": { + "medusa-order-seed": "dist/scripts/bin/run-seed.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/medusajs/medusa", + "directory": "packages/order" + }, + "publishConfig": { + "access": "public" + }, + "author": "Medusa", + "license": "MIT", + "scripts": { + "watch": "tsc --build --watch", + "watch:test": "tsc --build tsconfig.spec.json --watch", + "prepublishOnly": "cross-env NODE_ENV=production tsc --build && tsc-alias -p tsconfig.json", + "build": "rimraf dist && tsc --build && tsc-alias -p tsconfig.json", + "test": "jest --runInBand --bail --forceExit -- src/**/__tests__/**/*.ts", + "test:integration": "jest --runInBand --forceExit -- integration-tests/**/__tests__/**/*.ts", + "migration:generate": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:generate", + "migration:initial": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create --initial", + "migration:create": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create", + "migration:up": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:up", + "orm:cache:clear": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm cache:clear" + }, + "devDependencies": { + "@mikro-orm/cli": "5.9.7", + "cross-env": "^5.2.1", + "jest": "^29.6.3", + "medusa-test-utils": "^1.1.40", + "rimraf": "^3.0.2", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "tsc-alias": "^1.8.6", + "typescript": "^5.1.6" + }, + "dependencies": { + "@medusajs/modules-sdk": "^1.12.4", + "@medusajs/types": "^1.11.8", + "@medusajs/utils": "^1.11.1", + "@mikro-orm/core": "5.9.7", + "@mikro-orm/migrations": "5.9.7", + "@mikro-orm/postgresql": "5.9.7", + "awilix": "^8.0.0", + "dotenv": "^16.1.4", + "knex": "2.4.2" + } +} diff --git a/packages/order/src/index.ts b/packages/order/src/index.ts new file mode 100644 index 0000000000..9b5c17201b --- /dev/null +++ b/packages/order/src/index.ts @@ -0,0 +1,14 @@ +import { initializeFactory, Modules } from "@medusajs/modules-sdk" +import { moduleDefinition } from "./module-definition" + +export * from "./models" +export * from "./services" +export * from "./types" + +export const initialize = initializeFactory({ + moduleName: Modules.ORDER, + moduleDefinition, +}) +export const runMigrations = moduleDefinition.runMigrations +export const revertMigration = moduleDefinition.revertMigration +export default moduleDefinition diff --git a/packages/order/src/joiner-config.ts b/packages/order/src/joiner-config.ts new file mode 100644 index 0000000000..f8336e6ac2 --- /dev/null +++ b/packages/order/src/joiner-config.ts @@ -0,0 +1,26 @@ +import { Modules } from "@medusajs/modules-sdk" +import { ModuleJoinerConfig } from "@medusajs/types" +import { MapToConfig } from "@medusajs/utils" + +export const LinkableKeys: Record = { + order_id: "Order", + order_item_id: "OrderLineItem", +} + +const entityLinkableKeysMap: MapToConfig = {} +Object.entries(LinkableKeys).forEach(([key, value]) => { + entityLinkableKeysMap[value] ??= [] + entityLinkableKeysMap[value].push({ + mapTo: key, + valueFrom: key.split("_").pop()!, + }) +}) + +export const entityNameToLinkableKeysMap: MapToConfig = entityLinkableKeysMap + +export const joinerConfig: ModuleJoinerConfig = { + serviceName: Modules.ORDER, + primaryKeys: ["id"], + linkableKeys: LinkableKeys, + alias: [], +} as ModuleJoinerConfig diff --git a/packages/order/src/models/address.ts b/packages/order/src/models/address.ts new file mode 100644 index 0000000000..d2a4fdc9a8 --- /dev/null +++ b/packages/order/src/models/address.ts @@ -0,0 +1,90 @@ +import { DAL } from "@medusajs/types" +import { + createPsqlIndexStatementHelper, + generateEntityId, +} from "@medusajs/utils" +import { + BeforeCreate, + Entity, + OnInit, + OptionalProps, + PrimaryKey, + Property, +} from "@mikro-orm/core" + +type OptionalAddressProps = DAL.EntityDateColumns + +const customerIdIndex = createPsqlIndexStatementHelper({ + tableName: "order_address", + columns: "customer_id", +}) + +@Entity({ tableName: "order_address" }) +export default class Address { + [OptionalProps]: OptionalAddressProps + + @PrimaryKey({ columnType: "text" }) + id!: string + + @Property({ columnType: "text", nullable: true }) + @customerIdIndex.MikroORMIndex() + customer_id: string | null = null + + @Property({ columnType: "text", nullable: true }) + company: string | null = null + + @Property({ columnType: "text", nullable: true }) + first_name: string | null = null + + @Property({ columnType: "text", nullable: true }) + last_name: string | null = null + + @Property({ columnType: "text", nullable: true }) + address_1: string | null = null + + @Property({ columnType: "text", nullable: true }) + address_2: string | null = null + + @Property({ columnType: "text", nullable: true }) + city: string | null = null + + @Property({ columnType: "text", nullable: true }) + country_code: string | null = null + + @Property({ columnType: "text", nullable: true }) + province: string | null = null + + @Property({ columnType: "text", nullable: true }) + postal_code: string | null = null + + @Property({ columnType: "text", nullable: true }) + phone: string | null = null + + @Property({ columnType: "jsonb", nullable: true }) + metadata: Record | null = null + + @Property({ + onCreate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + created_at: Date + + @Property({ + onCreate: () => new Date(), + onUpdate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + updated_at: Date + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "ordaddr") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "ordaddr") + } +} diff --git a/packages/order/src/models/adjustment-line.ts b/packages/order/src/models/adjustment-line.ts new file mode 100644 index 0000000000..8e117eb208 --- /dev/null +++ b/packages/order/src/models/adjustment-line.ts @@ -0,0 +1,52 @@ +import { BigNumberRawValue, DAL } from "@medusajs/types" +import { BigNumber } from "@medusajs/utils" +import { OptionalProps, PrimaryKey, Property } from "@mikro-orm/core" + +type OptionalAdjustmentLineProps = DAL.EntityDateColumns + +/** + * As per the Mikro ORM docs, superclasses should use the abstract class definition + * Source: https://mikro-orm.io/docs/inheritance-mapping + */ +export default abstract class AdjustmentLine { + [OptionalProps]: OptionalAdjustmentLineProps + + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ columnType: "text", nullable: true }) + description: string | null = null + + @Property({ + columnType: "text", + nullable: true, + }) + promotion_id: string | null = null + + @Property({ columnType: "text", nullable: true }) + code: string | null = null + + @Property({ columnType: "numeric" }) + amount: BigNumber | number + + @Property({ columnType: "jsonb" }) + raw_amount: BigNumberRawValue + + @Property({ columnType: "text", nullable: true }) + provider_id: string | null = null + + @Property({ + onCreate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + created_at: Date + + @Property({ + onCreate: () => new Date(), + onUpdate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + updated_at: Date +} diff --git a/packages/order/src/models/index.ts b/packages/order/src/models/index.ts new file mode 100644 index 0000000000..4a8a606bfc --- /dev/null +++ b/packages/order/src/models/index.ts @@ -0,0 +1,8 @@ +export { default as Address } from "./address" +export { default as LineItem } from "./line-item" +export { default as LineItemAdjustment } from "./line-item-adjustment" +export { default as LineItemTaxLine } from "./line-item-tax-line" +export { default as Order } from "./order" +export { default as ShippingMethod } from "./shipping-method" +export { default as ShippingMethodAdjustment } from "./shipping-method-adjustment" +export { default as ShippingMethodTaxLine } from "./shipping-method-tax-line" diff --git a/packages/order/src/models/line-item-adjustment.ts b/packages/order/src/models/line-item-adjustment.ts new file mode 100644 index 0000000000..bb40a89ce1 --- /dev/null +++ b/packages/order/src/models/line-item-adjustment.ts @@ -0,0 +1,38 @@ +import { generateEntityId } from "@medusajs/utils" +import { + BeforeCreate, + Cascade, + Check, + Entity, + ManyToOne, + OnInit, + Property, +} from "@mikro-orm/core" +import AdjustmentLine from "./adjustment-line" +import LineItem from "./line-item" + +@Entity({ tableName: "order_line_item_adjustment" }) +@Check({ + expression: (columns) => `${columns.amount} >= 0`, +}) +export default class LineItemAdjustment extends AdjustmentLine { + @ManyToOne({ + entity: () => LineItem, + index: "IDX_order_line_item_adjustment_item_id", + cascade: [Cascade.REMOVE, Cascade.PERSIST], + }) + item: LineItem + + @Property({ columnType: "text" }) + item_id: string + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "ordliadj") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "ordliadj") + } +} diff --git a/packages/order/src/models/line-item-tax-line.ts b/packages/order/src/models/line-item-tax-line.ts new file mode 100644 index 0000000000..52a81dd903 --- /dev/null +++ b/packages/order/src/models/line-item-tax-line.ts @@ -0,0 +1,34 @@ +import { generateEntityId } from "@medusajs/utils" +import { + BeforeCreate, + Cascade, + Entity, + ManyToOne, + OnInit, + Property, +} from "@mikro-orm/core" +import LineItem from "./line-item" +import TaxLine from "./tax-line" + +@Entity({ tableName: "order_line_item_tax_line" }) +export default class LineItemTaxLine extends TaxLine { + @ManyToOne({ + entity: () => LineItem, + index: "IDX_order_line_item_tax_line_item_id", + cascade: [Cascade.REMOVE, Cascade.PERSIST], + }) + item: LineItem + + @Property({ columnType: "text" }) + item_id: string + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "ordlitxl") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "ordlitxl") + } +} diff --git a/packages/order/src/models/line-item.ts b/packages/order/src/models/line-item.ts new file mode 100644 index 0000000000..551262dc02 --- /dev/null +++ b/packages/order/src/models/line-item.ts @@ -0,0 +1,192 @@ +import { BigNumberRawValue, DAL } from "@medusajs/types" +import { + BigNumber, + createPsqlIndexStatementHelper, + generateEntityId, +} from "@medusajs/utils" +import { + BeforeCreate, + BeforeUpdate, + Cascade, + Collection, + Entity, + ManyToOne, + OnInit, + OneToMany, + OptionalProps, + PrimaryKey, + Property, +} from "@mikro-orm/core" +import LineItemAdjustment from "./line-item-adjustment" +import LineItemTaxLine from "./line-item-tax-line" +import Order from "./order" + +type OptionalLineItemProps = + | "is_discoutable" + | "is_tax_inclusive" + | "compare_at_unit_price" + | "requires_shipping" + | "order" + | DAL.EntityDateColumns + +const productIdIndex = createPsqlIndexStatementHelper({ + tableName: "order_line_item", + columns: "product_id", +}) + +const variantIdIndex = createPsqlIndexStatementHelper({ + tableName: "order_line_item", + columns: "variant_id", +}) + +@Entity({ tableName: "order_line_item" }) +export default class LineItem { + [OptionalProps]?: OptionalLineItemProps + + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ columnType: "text" }) + order_id: string + + @ManyToOne({ + entity: () => Order, + onDelete: "cascade", + index: "IDX_order_line_item_order_id", + cascade: [Cascade.REMOVE, Cascade.PERSIST], + }) + order: Order + + @Property({ columnType: "text" }) + title: string + + @Property({ columnType: "text", nullable: true }) + subtitle: string | null = null + + @Property({ columnType: "text", nullable: true }) + thumbnail: string | null = null + + @Property({ columnType: "numeric" }) + quantity: BigNumber | number + + @Property({ columnType: "jsonb" }) + raw_quantity: BigNumberRawValue + + @Property({ + columnType: "text", + nullable: true, + }) + @variantIdIndex.MikroORMIndex() + variant_id: string | null = null + + @Property({ + columnType: "text", + nullable: true, + }) + @productIdIndex.MikroORMIndex() + product_id: string | null = null + + @Property({ columnType: "text", nullable: true }) + product_title: string | null = null + + @Property({ columnType: "text", nullable: true }) + product_description: string | null = null + + @Property({ columnType: "text", nullable: true }) + product_subtitle: string | null = null + + @Property({ columnType: "text", nullable: true }) + product_type: string | null = null + + @Property({ columnType: "text", nullable: true }) + product_collection: string | null = null + + @Property({ columnType: "text", nullable: true }) + product_handle: string | null = null + + @Property({ columnType: "text", nullable: true }) + variant_sku: string | null = null + + @Property({ columnType: "text", nullable: true }) + variant_barcode: string | null = null + + @Property({ columnType: "text", nullable: true }) + variant_title: string | null = null + + @Property({ columnType: "jsonb", nullable: true }) + variant_option_values: Record | null = null + + @Property({ columnType: "boolean" }) + requires_shipping = true + + @Property({ columnType: "boolean" }) + is_discountable = true + + @Property({ columnType: "boolean" }) + is_tax_inclusive = false + + @Property({ columnType: "numeric", nullable: true }) + compare_at_unit_price?: BigNumber | number | null = null + + @Property({ columnType: "jsonb", nullable: true }) + raw_compare_at_unit_price: BigNumberRawValue | null = null + + @Property({ columnType: "numeric" }) + unit_price: BigNumber | number + + @Property({ columnType: "jsonb" }) + raw_unit_price: BigNumberRawValue + + @OneToMany(() => LineItemTaxLine, (taxLine) => taxLine.item, { + cascade: [Cascade.REMOVE], + }) + tax_lines = new Collection(this) + + @OneToMany(() => LineItemAdjustment, (adjustment) => adjustment.item, { + cascade: [Cascade.REMOVE], + }) + adjustments = new Collection(this) + + @Property({ + onCreate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + created_at: Date + + @Property({ + onCreate: () => new Date(), + onUpdate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + updated_at: Date + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "ordli") + + const val = new BigNumber(this.raw_unit_price ?? this.unit_price) + + this.unit_price = val.numeric + this.raw_unit_price = val.raw! + } + + @BeforeUpdate() + onUpdate() { + const val = new BigNumber(this.raw_unit_price ?? this.unit_price) + + this.unit_price = val.numeric + this.raw_unit_price = val.raw as BigNumberRawValue + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "ordli") + + const val = new BigNumber(this.raw_unit_price ?? this.unit_price) + + this.unit_price = val.numeric + this.raw_unit_price = val.raw! + } +} diff --git a/packages/order/src/models/order.ts b/packages/order/src/models/order.ts new file mode 100644 index 0000000000..09e9147425 --- /dev/null +++ b/packages/order/src/models/order.ts @@ -0,0 +1,168 @@ +import { DAL } from "@medusajs/types" +import { + OrderStatus, + createPsqlIndexStatementHelper, + generateEntityId, +} from "@medusajs/utils" +import { + BeforeCreate, + Cascade, + Collection, + Entity, + Enum, + ManyToOne, + OnInit, + OneToMany, + OptionalProps, + PrimaryKey, + Property, +} from "@mikro-orm/core" +import Address from "./address" +import LineItem from "./line-item" +import ShippingMethod from "./shipping-method" + +type OptionalOrderProps = + | "shipping_address" + | "billing_address" + | DAL.EntityDateColumns + +const regionIdIndex = createPsqlIndexStatementHelper({ + tableName: "order", + columns: "region_id", + where: "deleted_at IS NOT NULL", +}) + +const customerIdIndex = createPsqlIndexStatementHelper({ + tableName: "order", + columns: "customer_id", + where: "deleted_at IS NOT NULL", +}) + +const salesChannelIdIndex = createPsqlIndexStatementHelper({ + tableName: "order", + columns: "customer_id", + where: "deleted_at IS NOT NULL", +}) + +const orderDeletedAtIndex = createPsqlIndexStatementHelper({ + tableName: "order", + columns: "deleted_at", + where: "deleted_at IS NOT NULL", +}) + +const currencyCodeIndex = createPsqlIndexStatementHelper({ + tableName: "order", + columns: "currency_code", + where: "deleted_at IS NOT NULL", +}) + +@Entity({ tableName: "order" }) +export default class Order { + [OptionalProps]?: OptionalOrderProps + + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ + columnType: "text", + nullable: true, + }) + @regionIdIndex.MikroORMIndex() + region_id: string | null = null + + @Property({ + columnType: "text", + nullable: true, + }) + @customerIdIndex.MikroORMIndex() + customer_id: string | null = null + + @Property({ + columnType: "text", + nullable: true, + }) + @salesChannelIdIndex.MikroORMIndex() + sales_channel_id: string | null = null + + @Enum({ items: () => OrderStatus, default: OrderStatus.PENDING }) + status: OrderStatus + + @Property({ columnType: "text", nullable: true }) + email: string | null = null + + @Property({ columnType: "text" }) + @currencyCodeIndex.MikroORMIndex() + currency_code: string + + @Property({ columnType: "text", nullable: true }) + shipping_address_id?: string | null + + @ManyToOne({ + entity: () => Address, + fieldName: "shipping_address_id", + nullable: true, + index: "IDX_order_shipping_address_id", + cascade: [Cascade.PERSIST], + }) + shipping_address?: Address | null + + @Property({ columnType: "text", nullable: true }) + billing_address_id?: string | null + + @ManyToOne({ + entity: () => Address, + fieldName: "billing_address_id", + nullable: true, + index: "IDX_order_billing_address_id", + cascade: [Cascade.PERSIST], + }) + billing_address?: Address | null + + @Property({ columnType: "boolean", nullable: true }) + no_notification: boolean | null = null + + @Property({ columnType: "jsonb", nullable: true }) + metadata: Record | null = null + + @OneToMany(() => LineItem, (lineItem) => lineItem.order, { + cascade: [Cascade.REMOVE], + }) + items = new Collection(this) + + @OneToMany(() => ShippingMethod, (shippingMethod) => shippingMethod.order, { + cascade: [Cascade.REMOVE], + }) + shipping_methods = new Collection(this) + + @Property({ + onCreate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + created_at: Date + + @Property({ + onCreate: () => new Date(), + onUpdate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + updated_at: Date + + @Property({ columnType: "timestamptz", nullable: true }) + @orderDeletedAtIndex.MikroORMIndex() + deleted_at: Date | null = null + + @Property({ columnType: "timestamptz", nullable: true }) + canceled_at: Date | null = null + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "order") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "order") + } +} diff --git a/packages/order/src/models/shipping-method-adjustment.ts b/packages/order/src/models/shipping-method-adjustment.ts new file mode 100644 index 0000000000..5384bba84d --- /dev/null +++ b/packages/order/src/models/shipping-method-adjustment.ts @@ -0,0 +1,35 @@ +import { generateEntityId } from "@medusajs/utils" +import { + BeforeCreate, + Cascade, + Entity, + ManyToOne, + OnInit, + Property, +} from "@mikro-orm/core" +import AdjustmentLine from "./adjustment-line" +import ShippingMethod from "./shipping-method" + +@Entity({ tableName: "order_shipping_method_adjustment" }) +export default class ShippingMethodAdjustment extends AdjustmentLine { + @ManyToOne({ + entity: () => ShippingMethod, + fieldName: "shipping_method_id", + index: "IDX_order_shipping_method_adjustment_shipping_method_id", + cascade: [Cascade.REMOVE, Cascade.PERSIST], + }) + shipping_method: ShippingMethod + + @Property({ columnType: "text" }) + shipping_method_id: string + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "ordsmadj") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "ordsmadj") + } +} diff --git a/packages/order/src/models/shipping-method-tax-line.ts b/packages/order/src/models/shipping-method-tax-line.ts new file mode 100644 index 0000000000..c89ad24ed7 --- /dev/null +++ b/packages/order/src/models/shipping-method-tax-line.ts @@ -0,0 +1,35 @@ +import { generateEntityId } from "@medusajs/utils" +import { + BeforeCreate, + Cascade, + Entity, + ManyToOne, + OnInit, + Property, +} from "@mikro-orm/core" +import ShippingMethod from "./shipping-method" +import TaxLine from "./tax-line" + +@Entity({ tableName: "order_shipping_method_tax_line" }) +export default class ShippingMethodTaxLine extends TaxLine { + @ManyToOne({ + entity: () => ShippingMethod, + fieldName: "shipping_method_id", + index: "IDX_order_tax_line_shipping_method_id", + cascade: [Cascade.REMOVE, Cascade.PERSIST], + }) + shipping_method: ShippingMethod + + @Property({ columnType: "text" }) + shipping_method_id: string + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "ordsmtxl") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "ordsmtxl") + } +} diff --git a/packages/order/src/models/shipping-method.ts b/packages/order/src/models/shipping-method.ts new file mode 100644 index 0000000000..d878514cad --- /dev/null +++ b/packages/order/src/models/shipping-method.ts @@ -0,0 +1,134 @@ +import { BigNumberRawValue } from "@medusajs/types" +import { + BigNumber, + createPsqlIndexStatementHelper, + generateEntityId, +} from "@medusajs/utils" +import { + BeforeCreate, + Cascade, + Check, + Collection, + Entity, + ManyToOne, + OnInit, + OneToMany, + PrimaryKey, + Property, +} from "@mikro-orm/core" +import { BeforeUpdate } from "typeorm" +import Order from "./order" +import ShippingMethodAdjustment from "./shipping-method-adjustment" +import ShippingMethodTaxLine from "./shipping-method-tax-line" + +const shippingOptionIdIndex = createPsqlIndexStatementHelper({ + tableName: "order_shipping_method", + columns: "shipping_option_id", +}) + +@Entity({ tableName: "order_shipping_method" }) +@Check({ expression: (columns) => `${columns.amount} >= 0` }) +export default class ShippingMethod { + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ columnType: "text" }) + order_id: string + + @ManyToOne({ + entity: () => Order, + fieldName: "order_id", + index: "IDX_order_shipping_method_order_id", + cascade: [Cascade.REMOVE, Cascade.PERSIST], + }) + order: Order + + @Property({ columnType: "text" }) + name: string + + @Property({ columnType: "jsonb", nullable: true }) + description: string | null = null + + @Property({ columnType: "numeric" }) + amount: BigNumber | number + + @Property({ columnType: "jsonb" }) + raw_amount: BigNumberRawValue + + @Property({ columnType: "boolean" }) + is_tax_inclusive = false + + @Property({ + columnType: "text", + nullable: true, + }) + @shippingOptionIdIndex.MikroORMIndex() + shipping_option_id: string | null = null + + @Property({ columnType: "jsonb", nullable: true }) + data: Record | null = null + + @Property({ columnType: "jsonb", nullable: true }) + metadata: Record | null = null + + @OneToMany( + () => ShippingMethodTaxLine, + (taxLine) => taxLine.shipping_method, + { + cascade: [Cascade.REMOVE], + } + ) + tax_lines = new Collection(this) + + @OneToMany( + () => ShippingMethodAdjustment, + (adjustment) => adjustment.shipping_method, + { + cascade: [Cascade.REMOVE], + } + ) + adjustments = new Collection(this) + + @Property({ + onCreate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + created_at: Date + + @Property({ + onCreate: () => new Date(), + onUpdate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + updated_at: Date + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "ordsm") + + const val = new BigNumber(this.raw_amount ?? this.amount) + + this.amount = val.numeric + this.raw_amount = val.raw! + } + + @BeforeUpdate() + onUpdate() { + const val = new BigNumber(this.raw_amount ?? this.amount) + + this.amount = val.numeric + this.raw_amount = val.raw as BigNumberRawValue + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "ordsm") + + const val = new BigNumber(this.raw_amount ?? this.amount) + + this.amount = val.numeric + this.raw_amount = val.raw! + } +} diff --git a/packages/order/src/models/tax-line.ts b/packages/order/src/models/tax-line.ts new file mode 100644 index 0000000000..296aafc577 --- /dev/null +++ b/packages/order/src/models/tax-line.ts @@ -0,0 +1,48 @@ +import { BigNumberRawValue } from "@medusajs/types" +import { BigNumber } from "@medusajs/utils" +import { PrimaryKey, Property } from "@mikro-orm/core" + +/** + * As per the Mikro ORM docs, superclasses should use the abstract class definition + * Source: https://mikro-orm.io/docs/inheritance-mapping + */ +export default abstract class TaxLine { + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ columnType: "text", nullable: true }) + description?: string | null + + @Property({ + columnType: "text", + nullable: true, + }) + tax_rate_id?: string | null + + @Property({ columnType: "text" }) + code: string + + @Property({ columnType: "numeric" }) + rate: BigNumber | number + + @Property({ columnType: "jsonb" }) + raw_rate: BigNumberRawValue + + @Property({ columnType: "text", nullable: true }) + provider_id?: string | null + + @Property({ + onCreate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + created_at: Date + + @Property({ + onCreate: () => new Date(), + onUpdate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + updated_at: Date +} diff --git a/packages/order/src/module-definition.ts b/packages/order/src/module-definition.ts new file mode 100644 index 0000000000..3a0d42e70d --- /dev/null +++ b/packages/order/src/module-definition.ts @@ -0,0 +1,44 @@ +import { Modules } from "@medusajs/modules-sdk" +import { ModuleExports } from "@medusajs/types" +import { ModulesSdkUtils } from "@medusajs/utils" +import * as Models from "@models" +import * as ModuleModels from "@models" +import * as ModuleRepositories from "@repositories" +import * as ModuleServices from "@services" +import { OrderModuleService } from "@services" + +const migrationScriptOptions = { + moduleName: Modules.ORDER, + models: Models, + pathToMigrations: __dirname + "/migrations", +} + +const runMigrations = ModulesSdkUtils.buildMigrationScript( + migrationScriptOptions +) + +const revertMigration = ModulesSdkUtils.buildRevertMigrationScript( + migrationScriptOptions +) + +const containerLoader = ModulesSdkUtils.moduleContainerLoaderFactory({ + moduleModels: ModuleModels, + moduleRepositories: ModuleRepositories, + moduleServices: ModuleServices, +}) + +const connectionLoader = ModulesSdkUtils.mikroOrmConnectionLoaderFactory({ + moduleName: Modules.ORDER, + moduleModels: Object.values(Models), + migrationsPath: __dirname + "/migrations", +}) + +const service = OrderModuleService +const loaders = [containerLoader, connectionLoader] as any + +export const moduleDefinition: ModuleExports = { + service, + loaders, + revertMigration, + runMigrations, +} diff --git a/packages/order/src/repositories/index.ts b/packages/order/src/repositories/index.ts new file mode 100644 index 0000000000..147c9cc259 --- /dev/null +++ b/packages/order/src/repositories/index.ts @@ -0,0 +1 @@ +export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils" diff --git a/packages/order/src/scripts/bin/run-seed.ts b/packages/order/src/scripts/bin/run-seed.ts new file mode 100644 index 0000000000..f32d9cdf33 --- /dev/null +++ b/packages/order/src/scripts/bin/run-seed.ts @@ -0,0 +1,29 @@ +#!/usr/bin/env node + +import { Modules } from "@medusajs/modules-sdk" +import { ModulesSdkUtils } from "@medusajs/utils" +import * as Models from "@models" +import { EOL } from "os" + +const args = process.argv +const path = args.pop() as string + +export default (async () => { + const { config } = await import("dotenv") + config() + if (!path) { + throw new Error( + `filePath is required.${EOL}Example: medusa-order-seed ` + ) + } + + const run = ModulesSdkUtils.buildSeedScript({ + moduleName: Modules.ORDER, + models: Models, + pathToMigrations: __dirname + "/../../migrations", + seedHandler: async ({ manager, data }) => { + // TODO: Add seed logic + }, + }) + await run({ path }) +})() diff --git a/packages/order/src/services/__tests__/noop.ts b/packages/order/src/services/__tests__/noop.ts new file mode 100644 index 0000000000..333c84c1dd --- /dev/null +++ b/packages/order/src/services/__tests__/noop.ts @@ -0,0 +1,5 @@ +describe("noop", function () { + it("should run", function () { + expect(true).toBe(true) + }) +}) diff --git a/packages/order/src/services/index.ts b/packages/order/src/services/index.ts new file mode 100644 index 0000000000..383ee9897a --- /dev/null +++ b/packages/order/src/services/index.ts @@ -0,0 +1 @@ +export { default as OrderModuleService } from "./order-module-service" diff --git a/packages/order/src/services/order-module-service.ts b/packages/order/src/services/order-module-service.ts new file mode 100644 index 0000000000..e41bc2f785 --- /dev/null +++ b/packages/order/src/services/order-module-service.ts @@ -0,0 +1,1280 @@ +import { + Context, + DAL, + FilterableLineItemTaxLineProps, + IOrderModuleService, + InternalModuleDeclaration, + ModuleJoinerConfig, + ModulesSdkTypes, + OrderTypes, +} from "@medusajs/types" +import { + InjectManager, + InjectTransactionManager, + MedusaContext, + MedusaError, + ModulesSdkUtils, + isObject, + isString, +} from "@medusajs/utils" +import { + Address, + LineItem, + LineItemAdjustment, + LineItemTaxLine, + Order, + ShippingMethod, + ShippingMethodAdjustment, + ShippingMethodTaxLine, +} from "@models" +import { + CreateOrderLineItemDTO, + CreateOrderLineItemTaxLineDTO, + CreateOrderShippingMethodDTO, + CreateOrderShippingMethodTaxLineDTO, + UpdateOrderLineItemDTO, + UpdateOrderLineItemTaxLineDTO, + UpdateOrderShippingMethodTaxLineDTO, +} from "@types" +import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config" + +type InjectedDependencies = { + baseRepository: DAL.RepositoryService + orderService: ModulesSdkTypes.InternalModuleService + addressService: ModulesSdkTypes.InternalModuleService + lineItemService: ModulesSdkTypes.InternalModuleService + shippingMethodAdjustmentService: ModulesSdkTypes.InternalModuleService + shippingMethodService: ModulesSdkTypes.InternalModuleService + lineItemAdjustmentService: ModulesSdkTypes.InternalModuleService + lineItemTaxLineService: ModulesSdkTypes.InternalModuleService + shippingMethodTaxLineService: ModulesSdkTypes.InternalModuleService +} + +const generateMethodForModels = [ + Address, + LineItem, + LineItemAdjustment, + LineItemTaxLine, + ShippingMethod, + ShippingMethodAdjustment, + ShippingMethodTaxLine, +] + +export default class OrderModuleService< + TOrder extends Order = Order, + TAddress extends Address = Address, + TLineItem extends LineItem = LineItem, + TLineItemAdjustment extends LineItemAdjustment = LineItemAdjustment, + TLineItemTaxLine extends LineItemTaxLine = LineItemTaxLine, + TShippingMethodAdjustment extends ShippingMethodAdjustment = ShippingMethodAdjustment, + TShippingMethodTaxLine extends ShippingMethodTaxLine = ShippingMethodTaxLine, + TShippingMethod extends ShippingMethod = ShippingMethod + > + extends ModulesSdkUtils.abstractModuleServiceFactory< + InjectedDependencies, + OrderTypes.OrderDTO, + { + Address: { dto: OrderTypes.OrderAddressDTO } + LineItem: { dto: OrderTypes.OrderLineItemDTO } + LineItemAdjustment: { dto: OrderTypes.OrderLineItemAdjustmentDTO } + LineItemTaxLine: { dto: OrderTypes.OrderLineItemTaxLineDTO } + ShippingMethod: { dto: OrderTypes.OrderShippingMethodDTO } + ShippingMethodAdjustment: { + dto: OrderTypes.OrderShippingMethodAdjustmentDTO + } + ShippingMethodTaxLine: { dto: OrderTypes.OrderShippingMethodTaxLineDTO } + } + >(Order, generateMethodForModels, entityNameToLinkableKeysMap) + implements IOrderModuleService +{ + protected baseRepository_: DAL.RepositoryService + protected orderService_: ModulesSdkTypes.InternalModuleService + protected addressService_: ModulesSdkTypes.InternalModuleService + protected lineItemService_: ModulesSdkTypes.InternalModuleService + protected shippingMethodAdjustmentService_: ModulesSdkTypes.InternalModuleService + protected shippingMethodService_: ModulesSdkTypes.InternalModuleService + protected lineItemAdjustmentService_: ModulesSdkTypes.InternalModuleService + protected lineItemTaxLineService_: ModulesSdkTypes.InternalModuleService + protected shippingMethodTaxLineService_: ModulesSdkTypes.InternalModuleService + + constructor( + { + baseRepository, + orderService, + addressService, + lineItemService, + shippingMethodAdjustmentService, + shippingMethodService, + lineItemAdjustmentService, + shippingMethodTaxLineService, + lineItemTaxLineService, + }: InjectedDependencies, + protected readonly moduleDeclaration: InternalModuleDeclaration + ) { + // @ts-ignore + super(...arguments) + + this.baseRepository_ = baseRepository + this.orderService_ = orderService + this.addressService_ = addressService + this.lineItemService_ = lineItemService + this.shippingMethodAdjustmentService_ = shippingMethodAdjustmentService + this.shippingMethodService_ = shippingMethodService + this.lineItemAdjustmentService_ = lineItemAdjustmentService + this.shippingMethodTaxLineService_ = shippingMethodTaxLineService + this.lineItemTaxLineService_ = lineItemTaxLineService + } + + __joinerConfig(): ModuleJoinerConfig { + return joinerConfig + } + + async create( + data: OrderTypes.CreateOrderDTO[], + sharedContext?: Context + ): Promise + + async create( + data: OrderTypes.CreateOrderDTO, + sharedContext?: Context + ): Promise + + @InjectManager("baseRepository_") + async create( + data: OrderTypes.CreateOrderDTO[] | OrderTypes.CreateOrderDTO, + @MedusaContext() sharedContext: Context = {} + ): Promise { + const input = Array.isArray(data) ? data : [data] + + const orders = await this.create_(input, sharedContext) + + const result = await this.list( + { id: orders.map((p) => p!.id) }, + { + relations: ["shipping_address", "billing_address"], + }, + sharedContext + ) + + return (Array.isArray(data) ? result : result[0]) as + | OrderTypes.OrderDTO + | OrderTypes.OrderDTO[] + } + + @InjectTransactionManager("baseRepository_") + protected async create_( + data: OrderTypes.CreateOrderDTO[], + @MedusaContext() sharedContext: Context = {} + ) { + const lineItemsToCreate: CreateOrderLineItemDTO[] = [] + const createdOrders: Order[] = [] + for (const { items, ...order } of data) { + const [created] = await this.orderService_.create([order], sharedContext) + + createdOrders.push(created) + + if (items?.length) { + const orderItems = items.map((item) => { + return { + ...item, + order_id: created.id, + } + }) + + lineItemsToCreate.push(...orderItems) + } + } + + if (lineItemsToCreate.length) { + await this.addLineItemsBulk_(lineItemsToCreate, sharedContext) + } + + return createdOrders + } + + async update( + data: OrderTypes.UpdateOrderDTO[], + sharedContext?: Context + ): Promise + + async update( + data: OrderTypes.UpdateOrderDTO, + sharedContext?: Context + ): Promise + + @InjectManager("baseRepository_") + async update( + data: OrderTypes.UpdateOrderDTO[] | OrderTypes.UpdateOrderDTO, + @MedusaContext() sharedContext: Context = {} + ): Promise { + const input = Array.isArray(data) ? data : [data] + const orders = await this.update_(input, sharedContext) + + const result = await this.list( + { id: orders.map((p) => p!.id) }, + { + relations: ["shipping_address", "billing_address"], + }, + sharedContext + ) + + return (Array.isArray(data) ? result : result[0]) as + | OrderTypes.OrderDTO + | OrderTypes.OrderDTO[] + } + + @InjectTransactionManager("baseRepository_") + protected async update_( + data: OrderTypes.UpdateOrderDTO[], + @MedusaContext() sharedContext: Context = {} + ) { + return await this.orderService_.update(data, sharedContext) + } + + addLineItems( + data: OrderTypes.CreateOrderLineItemForOrderDTO + ): Promise + addLineItems( + data: OrderTypes.CreateOrderLineItemForOrderDTO[] + ): Promise + addLineItems( + orderId: string, + items: OrderTypes.CreateOrderLineItemDTO[], + sharedContext?: Context + ): Promise + + @InjectManager("baseRepository_") + async addLineItems( + orderIdOrData: + | string + | OrderTypes.CreateOrderLineItemForOrderDTO[] + | OrderTypes.CreateOrderLineItemForOrderDTO, + data?: + | OrderTypes.CreateOrderLineItemDTO[] + | OrderTypes.CreateOrderLineItemDTO, + @MedusaContext() sharedContext: Context = {} + ): Promise { + let items: LineItem[] = [] + if (isString(orderIdOrData)) { + items = await this.addLineItems_( + orderIdOrData, + data as OrderTypes.CreateOrderLineItemDTO[], + sharedContext + ) + } else { + const data = Array.isArray(orderIdOrData) + ? orderIdOrData + : [orderIdOrData] + items = await this.addLineItemsBulk_(data, sharedContext) + } + + return await this.baseRepository_.serialize( + items, + { + populate: true, + } + ) + } + + @InjectTransactionManager("baseRepository_") + protected async addLineItems_( + orderId: string, + items: OrderTypes.CreateOrderLineItemDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const order = await this.retrieve( + orderId, + { select: ["id"] }, + sharedContext + ) + + const toUpdate: CreateOrderLineItemDTO[] = items.map((item) => { + return { + ...item, + order_id: order.id, + } + }) + + return await this.addLineItemsBulk_(toUpdate, sharedContext) + } + + @InjectTransactionManager("baseRepository_") + protected async addLineItemsBulk_( + data: CreateOrderLineItemDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + return await this.lineItemService_.create(data, sharedContext) + } + + updateLineItems( + data: OrderTypes.UpdateOrderLineItemWithSelectorDTO[] + ): Promise + updateLineItems( + selector: Partial, + data: OrderTypes.UpdateOrderLineItemDTO, + sharedContext?: Context + ): Promise + updateLineItems( + lineItemId: string, + data: Partial, + sharedContext?: Context + ): Promise + + @InjectManager("baseRepository_") + async updateLineItems( + lineItemIdOrDataOrSelector: + | string + | OrderTypes.UpdateOrderLineItemWithSelectorDTO[] + | Partial, + data?: + | OrderTypes.UpdateOrderLineItemDTO + | Partial, + @MedusaContext() sharedContext: Context = {} + ): Promise { + let items: LineItem[] = [] + if (isString(lineItemIdOrDataOrSelector)) { + const item = await this.updateLineItem_( + lineItemIdOrDataOrSelector, + data as Partial, + sharedContext + ) + + return await this.baseRepository_.serialize( + item, + { + populate: true, + } + ) + } + + const toUpdate = Array.isArray(lineItemIdOrDataOrSelector) + ? lineItemIdOrDataOrSelector + : [ + { + selector: lineItemIdOrDataOrSelector, + data: data, + } as OrderTypes.UpdateOrderLineItemWithSelectorDTO, + ] + + items = await this.updateLineItemsWithSelector_(toUpdate, sharedContext) + + return await this.baseRepository_.serialize( + items, + { + populate: true, + } + ) + } + + @InjectTransactionManager("baseRepository_") + protected async updateLineItem_( + lineItemId: string, + data: Partial, + @MedusaContext() sharedContext: Context = {} + ): Promise { + const [item] = await this.lineItemService_.update( + [{ id: lineItemId, ...data }], + sharedContext + ) + + return item + } + + @InjectTransactionManager("baseRepository_") + protected async updateLineItemsWithSelector_( + updates: OrderTypes.UpdateOrderLineItemWithSelectorDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + let toUpdate: UpdateOrderLineItemDTO[] = [] + for (const { selector, data } of updates) { + const items = await this.listLineItems({ ...selector }, {}, sharedContext) + + items.forEach((item) => { + toUpdate.push({ + ...data, + id: item.id, + }) + }) + } + + return await this.lineItemService_.update(toUpdate, sharedContext) + } + + async removeLineItems( + itemIds: string[], + sharedContext?: Context + ): Promise + async removeLineItems(itemIds: string, sharedContext?: Context): Promise + async removeLineItems( + selector: Partial, + sharedContext?: Context + ): Promise + + @InjectTransactionManager("baseRepository_") + async removeLineItems( + itemIdsOrSelector: string | string[] | Partial, + @MedusaContext() sharedContext: Context = {} + ): Promise { + let toDelete: string[] + + if (isObject(itemIdsOrSelector)) { + const items = await this.listLineItems( + { ...itemIdsOrSelector } as Partial, + {}, + sharedContext + ) + + toDelete = items.map((item) => item.id) + } else { + toDelete = Array.isArray(itemIdsOrSelector) + ? itemIdsOrSelector + : [itemIdsOrSelector] + } + + await this.lineItemService_.delete(toDelete, sharedContext) + } + + async createAddresses( + data: OrderTypes.CreateOrderAddressDTO, + sharedContext?: Context + ): Promise + async createAddresses( + data: OrderTypes.CreateOrderAddressDTO[], + sharedContext?: Context + ): Promise + + @InjectManager("baseRepository_") + async createAddresses( + data: OrderTypes.CreateOrderAddressDTO[] | OrderTypes.CreateOrderAddressDTO, + @MedusaContext() sharedContext: Context = {} + ): Promise { + const input = Array.isArray(data) ? data : [data] + const addresses = await this.createAddresses_(input, sharedContext) + + const result = await this.listAddresses( + { id: addresses.map((p) => p.id) }, + {}, + sharedContext + ) + + return (Array.isArray(data) ? result : result[0]) as + | OrderTypes.OrderAddressDTO + | OrderTypes.OrderAddressDTO[] + } + + @InjectTransactionManager("baseRepository_") + protected async createAddresses_( + data: OrderTypes.CreateOrderAddressDTO[], + @MedusaContext() sharedContext: Context = {} + ) { + return await this.addressService_.create(data, sharedContext) + } + + async updateAddresses( + data: OrderTypes.UpdateOrderAddressDTO, + sharedContext?: Context + ): Promise + async updateAddresses( + data: OrderTypes.UpdateOrderAddressDTO[], + sharedContext?: Context + ): Promise + + @InjectManager("baseRepository_") + async updateAddresses( + data: OrderTypes.UpdateOrderAddressDTO[] | OrderTypes.UpdateOrderAddressDTO, + @MedusaContext() sharedContext: Context = {} + ): Promise { + const input = Array.isArray(data) ? data : [data] + const addresses = await this.updateAddresses_(input, sharedContext) + + const result = await this.listAddresses( + { id: addresses.map((p) => p.id) }, + {}, + sharedContext + ) + + return (Array.isArray(data) ? result : result[0]) as + | OrderTypes.OrderAddressDTO + | OrderTypes.OrderAddressDTO[] + } + + @InjectTransactionManager("baseRepository_") + protected async updateAddresses_( + data: OrderTypes.UpdateOrderAddressDTO[], + @MedusaContext() sharedContext: Context = {} + ) { + return await this.addressService_.update(data, sharedContext) + } + + async addShippingMethods( + data: OrderTypes.CreateOrderShippingMethodDTO + ): Promise + async addShippingMethods( + data: OrderTypes.CreateOrderShippingMethodDTO[] + ): Promise + async addShippingMethods( + orderId: string, + methods: OrderTypes.CreateOrderShippingMethodForSingleOrderDTO[], + sharedContext?: Context + ): Promise + + @InjectManager("baseRepository_") + async addShippingMethods( + orderIdOrData: + | string + | OrderTypes.CreateOrderShippingMethodDTO[] + | OrderTypes.CreateOrderShippingMethodDTO, + data?: + | OrderTypes.CreateOrderShippingMethodDTO[] + | OrderTypes.CreateOrderShippingMethodForSingleOrderDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise< + OrderTypes.OrderShippingMethodDTO[] | OrderTypes.OrderShippingMethodDTO + > { + let methods: ShippingMethod[] + if (isString(orderIdOrData)) { + methods = await this.addShippingMethods_( + orderIdOrData, + data as OrderTypes.CreateOrderShippingMethodForSingleOrderDTO[], + sharedContext + ) + } else { + const data = Array.isArray(orderIdOrData) + ? orderIdOrData + : [orderIdOrData] + methods = await this.addShippingMethodsBulk_( + data as OrderTypes.CreateOrderShippingMethodDTO[], + sharedContext + ) + } + + return await this.baseRepository_.serialize< + OrderTypes.OrderShippingMethodDTO[] + >(methods, { populate: true }) + } + + @InjectTransactionManager("baseRepository_") + protected async addShippingMethods_( + orderId: string, + data: OrderTypes.CreateOrderShippingMethodForSingleOrderDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const order = await this.retrieve( + orderId, + { select: ["id"] }, + sharedContext + ) + + const methods = data.map((method) => { + return { + ...method, + order_id: order.id, + } + }) + + return await this.addShippingMethodsBulk_(methods, sharedContext) + } + + @InjectTransactionManager("baseRepository_") + protected async addShippingMethodsBulk_( + data: OrderTypes.CreateOrderShippingMethodDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + return await this.shippingMethodService_.create( + data as unknown as CreateOrderShippingMethodDTO[], + sharedContext + ) + } + + async removeShippingMethods( + methodIds: string[], + sharedContext?: Context + ): Promise + async removeShippingMethods( + methodIds: string, + sharedContext?: Context + ): Promise + async removeShippingMethods( + selector: Partial, + sharedContext?: Context + ): Promise + + @InjectTransactionManager("baseRepository_") + async removeShippingMethods( + methodIdsOrSelector: + | string + | string[] + | Partial, + @MedusaContext() sharedContext: Context = {} + ): Promise { + let toDelete: string[] + if (isObject(methodIdsOrSelector)) { + const methods = await this.listShippingMethods( + { + ...(methodIdsOrSelector as Partial), + }, + {}, + sharedContext + ) + + toDelete = methods.map((m) => m.id) + } else { + toDelete = Array.isArray(methodIdsOrSelector) + ? methodIdsOrSelector + : [methodIdsOrSelector] + } + await this.shippingMethodService_.delete(toDelete, sharedContext) + } + + async addLineItemAdjustments( + adjustments: OrderTypes.CreateOrderLineItemAdjustmentDTO[] + ): Promise + async addLineItemAdjustments( + adjustment: OrderTypes.CreateOrderLineItemAdjustmentDTO + ): Promise + async addLineItemAdjustments( + orderId: string, + adjustments: OrderTypes.CreateOrderLineItemAdjustmentDTO[], + sharedContext?: Context + ): Promise + + @InjectTransactionManager("baseRepository_") + async addLineItemAdjustments( + orderIdOrData: + | string + | OrderTypes.CreateOrderLineItemAdjustmentDTO[] + | OrderTypes.CreateOrderLineItemAdjustmentDTO, + adjustments?: OrderTypes.CreateOrderLineItemAdjustmentDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + let addedAdjustments: LineItemAdjustment[] = [] + if (isString(orderIdOrData)) { + const order = await this.retrieve( + orderIdOrData, + { select: ["id"], relations: ["items"] }, + sharedContext + ) + + const lineIds = order.items?.map((item) => item.id) + + for (const adj of adjustments || []) { + if (!lineIds?.includes(adj.item_id)) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Line item with id ${adj.item_id} does not exist on order with id ${orderIdOrData}` + ) + } + } + + addedAdjustments = await this.lineItemAdjustmentService_.create( + adjustments as OrderTypes.CreateOrderLineItemAdjustmentDTO[], + sharedContext + ) + } else { + const data = Array.isArray(orderIdOrData) + ? orderIdOrData + : [orderIdOrData] + + addedAdjustments = await this.lineItemAdjustmentService_.create( + data as OrderTypes.CreateOrderLineItemAdjustmentDTO[], + sharedContext + ) + } + + return await this.baseRepository_.serialize< + OrderTypes.OrderLineItemAdjustmentDTO[] + >(addedAdjustments, { + populate: true, + }) + } + + @InjectTransactionManager("baseRepository_") + async setLineItemAdjustments( + orderId: string, + adjustments: ( + | OrderTypes.CreateOrderLineItemAdjustmentDTO + | OrderTypes.UpdateOrderLineItemAdjustmentDTO + )[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const order = await this.retrieve( + orderId, + { select: ["id"], relations: ["items.adjustments"] }, + sharedContext + ) + + const existingAdjustments = await this.listLineItemAdjustments( + { item: { order_id: order.id } }, + { select: ["id"] }, + sharedContext + ) + + const adjustmentsSet = new Set( + adjustments + .map((a) => (a as OrderTypes.UpdateOrderLineItemAdjustmentDTO).id) + .filter(Boolean) + ) + + const toDelete: OrderTypes.OrderLineItemAdjustmentDTO[] = [] + + // From the existing adjustments, find the ones that are not passed in adjustments + existingAdjustments.forEach( + (adj: OrderTypes.OrderLineItemAdjustmentDTO) => { + if (!adjustmentsSet.has(adj.id)) { + toDelete.push(adj) + } + } + ) + + if (toDelete.length) { + await this.lineItemAdjustmentService_.delete( + toDelete.map((adj) => adj!.id), + sharedContext + ) + } + + let result = await this.lineItemAdjustmentService_.upsert( + adjustments, + sharedContext + ) + + return await this.baseRepository_.serialize< + OrderTypes.OrderLineItemAdjustmentDTO[] + >(result, { + populate: true, + }) + } + + async removeLineItemAdjustments( + adjustmentIds: string[], + sharedContext?: Context + ): Promise + async removeLineItemAdjustments( + adjustmentId: string, + sharedContext?: Context + ): Promise + async removeLineItemAdjustments( + selector: Partial, + sharedContext?: Context + ): Promise + + async removeLineItemAdjustments( + adjustmentIdsOrSelector: + | string + | string[] + | Partial, + @MedusaContext() sharedContext: Context = {} + ): Promise { + let ids: string[] + if (isObject(adjustmentIdsOrSelector)) { + const adjustments = await this.listLineItemAdjustments( + { + ...adjustmentIdsOrSelector, + } as Partial, + { select: ["id"] }, + sharedContext + ) + + ids = adjustments.map((adj) => adj.id) + } else { + ids = Array.isArray(adjustmentIdsOrSelector) + ? adjustmentIdsOrSelector + : [adjustmentIdsOrSelector] + } + + await this.lineItemAdjustmentService_.delete(ids, sharedContext) + } + + @InjectTransactionManager("baseRepository_") + async setShippingMethodAdjustments( + orderId: string, + adjustments: ( + | OrderTypes.CreateOrderShippingMethodAdjustmentDTO + | OrderTypes.UpdateOrderShippingMethodAdjustmentDTO + )[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const order = await this.retrieve( + orderId, + { select: ["id"], relations: ["shipping_methods.adjustments"] }, + sharedContext + ) + + const existingAdjustments = await this.listShippingMethodAdjustments( + { shipping_method: { order_id: order.id } }, + { select: ["id"] }, + sharedContext + ) + + const adjustmentsSet = new Set( + adjustments + .map( + (a) => (a as OrderTypes.UpdateOrderShippingMethodAdjustmentDTO)?.id + ) + .filter(Boolean) + ) + + const toDelete: OrderTypes.OrderShippingMethodAdjustmentDTO[] = [] + + // From the existing adjustments, find the ones that are not passed in adjustments + existingAdjustments.forEach( + (adj: OrderTypes.OrderShippingMethodAdjustmentDTO) => { + if (!adjustmentsSet.has(adj.id)) { + toDelete.push(adj) + } + } + ) + + if (toDelete.length) { + await this.shippingMethodAdjustmentService_.delete( + toDelete.map((adj) => adj!.id), + sharedContext + ) + } + + const result = await this.shippingMethodAdjustmentService_.upsert( + adjustments, + sharedContext + ) + + return await this.baseRepository_.serialize< + OrderTypes.OrderShippingMethodAdjustmentDTO[] + >(result, { + populate: true, + }) + } + + async addShippingMethodAdjustments( + adjustments: OrderTypes.CreateOrderShippingMethodAdjustmentDTO[] + ): Promise + async addShippingMethodAdjustments( + adjustment: OrderTypes.CreateOrderShippingMethodAdjustmentDTO + ): Promise + async addShippingMethodAdjustments( + orderId: string, + adjustments: OrderTypes.CreateOrderShippingMethodAdjustmentDTO[], + sharedContext?: Context + ): Promise + + @InjectTransactionManager("baseRepository_") + async addShippingMethodAdjustments( + orderIdOrData: + | string + | OrderTypes.CreateOrderShippingMethodAdjustmentDTO[] + | OrderTypes.CreateOrderShippingMethodAdjustmentDTO, + adjustments?: OrderTypes.CreateOrderShippingMethodAdjustmentDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise< + | OrderTypes.OrderShippingMethodAdjustmentDTO[] + | OrderTypes.OrderShippingMethodAdjustmentDTO + > { + let addedAdjustments: ShippingMethodAdjustment[] = [] + if (isString(orderIdOrData)) { + const order = await this.retrieve( + orderIdOrData, + { select: ["id"], relations: ["shipping_methods"] }, + sharedContext + ) + + const methodIds = order.shipping_methods?.map((method) => method.id) + + for (const adj of adjustments || []) { + if (!methodIds?.includes(adj.shipping_method_id)) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Shipping method with id ${adj.shipping_method_id} does not exist on order with id ${orderIdOrData}` + ) + } + } + + addedAdjustments = await this.shippingMethodAdjustmentService_.create( + adjustments as OrderTypes.CreateOrderShippingMethodAdjustmentDTO[], + sharedContext + ) + } else { + const data = Array.isArray(orderIdOrData) + ? orderIdOrData + : [orderIdOrData] + + addedAdjustments = await this.shippingMethodAdjustmentService_.create( + data as OrderTypes.CreateOrderShippingMethodAdjustmentDTO[], + sharedContext + ) + } + + if (isObject(orderIdOrData)) { + return await this.baseRepository_.serialize( + addedAdjustments[0], + { + populate: true, + } + ) + } + + return await this.baseRepository_.serialize< + OrderTypes.OrderShippingMethodAdjustmentDTO[] + >(addedAdjustments, { + populate: true, + }) + } + + async removeShippingMethodAdjustments( + adjustmentIds: string[], + sharedContext?: Context + ): Promise + async removeShippingMethodAdjustments( + adjustmentId: string, + sharedContext?: Context + ): Promise + async removeShippingMethodAdjustments( + selector: Partial, + sharedContext?: Context + ): Promise + + async removeShippingMethodAdjustments( + adjustmentIdsOrSelector: + | string + | string[] + | Partial, + @MedusaContext() sharedContext: Context = {} + ): Promise { + let ids: string[] + if (isObject(adjustmentIdsOrSelector)) { + const adjustments = await this.listShippingMethodAdjustments( + { + ...adjustmentIdsOrSelector, + } as Partial, + { select: ["id"] }, + sharedContext + ) + + ids = adjustments.map((adj) => adj.id) + } else { + ids = Array.isArray(adjustmentIdsOrSelector) + ? adjustmentIdsOrSelector + : [adjustmentIdsOrSelector] + } + + await this.shippingMethodAdjustmentService_.delete(ids, sharedContext) + } + + addLineItemTaxLines( + taxLines: OrderTypes.CreateOrderLineItemTaxLineDTO[] + ): Promise + addLineItemTaxLines( + taxLine: OrderTypes.CreateOrderLineItemTaxLineDTO + ): Promise + addLineItemTaxLines( + orderId: string, + taxLines: + | OrderTypes.CreateOrderLineItemTaxLineDTO[] + | OrderTypes.CreateOrderShippingMethodTaxLineDTO, + sharedContext?: Context + ): Promise + + @InjectTransactionManager("baseRepository_") + async addLineItemTaxLines( + orderIdOrData: + | string + | OrderTypes.CreateOrderLineItemTaxLineDTO[] + | OrderTypes.CreateOrderLineItemTaxLineDTO, + taxLines?: + | OrderTypes.CreateOrderLineItemTaxLineDTO[] + | OrderTypes.CreateOrderLineItemTaxLineDTO, + @MedusaContext() sharedContext: Context = {} + ): Promise< + OrderTypes.OrderLineItemTaxLineDTO[] | OrderTypes.OrderLineItemTaxLineDTO + > { + let addedTaxLines: LineItemTaxLine[] + if (isString(orderIdOrData)) { + // existence check + await this.retrieve(orderIdOrData, { select: ["id"] }, sharedContext) + + const lines = Array.isArray(taxLines) ? taxLines : [taxLines] + + addedTaxLines = await this.lineItemTaxLineService_.create( + lines as CreateOrderLineItemTaxLineDTO[], + sharedContext + ) + } else { + const data = Array.isArray(orderIdOrData) + ? orderIdOrData + : [orderIdOrData] + + addedTaxLines = await this.lineItemTaxLineService_.create( + data as CreateOrderLineItemTaxLineDTO[], + sharedContext + ) + } + + const serialized = await this.baseRepository_.serialize< + OrderTypes.OrderLineItemTaxLineDTO[] + >(addedTaxLines, { + populate: true, + }) + + if (isObject(orderIdOrData)) { + return serialized[0] + } + + return serialized + } + + @InjectTransactionManager("baseRepository_") + async setLineItemTaxLines( + orderId: string, + taxLines: ( + | OrderTypes.CreateOrderLineItemTaxLineDTO + | OrderTypes.UpdateOrderLineItemTaxLineDTO + )[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const order = await this.retrieve( + orderId, + { select: ["id"], relations: ["items.tax_lines"] }, + sharedContext + ) + + const existingTaxLines = await this.listLineItemTaxLines( + { item: { order_id: order.id } }, + { select: ["id"] }, + sharedContext + ) + + const taxLinesSet = new Set( + taxLines + .map( + (taxLine) => (taxLine as OrderTypes.UpdateOrderLineItemTaxLineDTO)?.id + ) + .filter(Boolean) + ) + + const toDelete: OrderTypes.OrderLineItemTaxLineDTO[] = [] + + // From the existing tax lines, find the ones that are not passed in taxLines + existingTaxLines.forEach((taxLine: OrderTypes.OrderLineItemTaxLineDTO) => { + if (!taxLinesSet.has(taxLine.id)) { + toDelete.push(taxLine) + } + }) + + if (toDelete.length) { + await this.lineItemTaxLineService_.delete( + toDelete.map((taxLine) => taxLine!.id), + sharedContext + ) + } + + const result = await this.lineItemTaxLineService_.upsert( + taxLines as UpdateOrderLineItemTaxLineDTO[], + sharedContext + ) + + return await this.baseRepository_.serialize< + OrderTypes.OrderLineItemTaxLineDTO[] + >(result, { + populate: true, + }) + } + + removeLineItemTaxLines( + taxLineIds: string[], + sharedContext?: Context + ): Promise + removeLineItemTaxLines( + taxLineIds: string, + sharedContext?: Context + ): Promise + removeLineItemTaxLines( + selector: FilterableLineItemTaxLineProps, + sharedContext?: Context + ): Promise + + async removeLineItemTaxLines( + taxLineIdsOrSelector: + | string + | string[] + | OrderTypes.FilterableOrderShippingMethodTaxLineProps, + @MedusaContext() sharedContext: Context = {} + ): Promise { + let ids: string[] + if (isObject(taxLineIdsOrSelector)) { + const taxLines = await this.listLineItemTaxLines( + { + ...(taxLineIdsOrSelector as OrderTypes.FilterableOrderLineItemTaxLineProps), + }, + { select: ["id"] }, + sharedContext + ) + + ids = taxLines.map((taxLine) => taxLine.id) + } else { + ids = Array.isArray(taxLineIdsOrSelector) + ? taxLineIdsOrSelector + : [taxLineIdsOrSelector] + } + + await this.lineItemTaxLineService_.delete(ids, sharedContext) + } + + addShippingMethodTaxLines( + taxLines: OrderTypes.CreateOrderShippingMethodTaxLineDTO[] + ): Promise + addShippingMethodTaxLines( + taxLine: OrderTypes.CreateOrderShippingMethodTaxLineDTO + ): Promise + addShippingMethodTaxLines( + orderId: string, + taxLines: + | OrderTypes.CreateOrderShippingMethodTaxLineDTO[] + | OrderTypes.CreateOrderShippingMethodTaxLineDTO, + sharedContext?: Context + ): Promise + + @InjectTransactionManager("baseRepository_") + async addShippingMethodTaxLines( + orderIdOrData: + | string + | OrderTypes.CreateOrderShippingMethodTaxLineDTO[] + | OrderTypes.CreateOrderShippingMethodTaxLineDTO, + taxLines?: + | OrderTypes.CreateOrderShippingMethodTaxLineDTO[] + | OrderTypes.CreateOrderShippingMethodTaxLineDTO, + @MedusaContext() sharedContext: Context = {} + ): Promise< + | OrderTypes.OrderShippingMethodTaxLineDTO[] + | OrderTypes.OrderShippingMethodTaxLineDTO + > { + let addedTaxLines: ShippingMethodTaxLine[] + if (isString(orderIdOrData)) { + // existence check + await this.retrieve(orderIdOrData, { select: ["id"] }, sharedContext) + + const lines = Array.isArray(taxLines) ? taxLines : [taxLines] + + addedTaxLines = await this.shippingMethodTaxLineService_.create( + lines as CreateOrderShippingMethodTaxLineDTO[], + sharedContext + ) + } else { + addedTaxLines = await this.shippingMethodTaxLineService_.create( + taxLines as CreateOrderShippingMethodTaxLineDTO[], + sharedContext + ) + } + + const serialized = + await this.baseRepository_.serialize( + addedTaxLines[0], + { + populate: true, + } + ) + + if (isObject(orderIdOrData)) { + return serialized[0] + } + + return serialized + } + + @InjectTransactionManager("baseRepository_") + async setShippingMethodTaxLines( + orderId: string, + taxLines: ( + | OrderTypes.CreateOrderShippingMethodTaxLineDTO + | OrderTypes.UpdateOrderShippingMethodTaxLineDTO + )[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const order = await this.retrieve( + orderId, + { select: ["id"], relations: ["shipping_methods.tax_lines"] }, + sharedContext + ) + + const existingTaxLines = await this.listShippingMethodTaxLines( + { shipping_method: { order_id: order.id } }, + { select: ["id"] }, + sharedContext + ) + + const taxLinesSet = new Set( + taxLines + .map( + (taxLine) => + (taxLine as OrderTypes.UpdateOrderShippingMethodTaxLineDTO)?.id + ) + .filter(Boolean) + ) + + const toDelete: OrderTypes.OrderShippingMethodTaxLineDTO[] = [] + + // From the existing tax lines, find the ones that are not passed in taxLines + existingTaxLines.forEach( + (taxLine: OrderTypes.OrderShippingMethodTaxLineDTO) => { + if (!taxLinesSet.has(taxLine.id)) { + toDelete.push(taxLine) + } + } + ) + + if (toDelete.length) { + await this.shippingMethodTaxLineService_.delete( + toDelete.map((taxLine) => taxLine!.id), + sharedContext + ) + } + + const result = await this.shippingMethodTaxLineService_.upsert( + taxLines as UpdateOrderShippingMethodTaxLineDTO[], + sharedContext + ) + + return await this.baseRepository_.serialize< + OrderTypes.OrderShippingMethodTaxLineDTO[] + >(result, { + populate: true, + }) + } + + removeShippingMethodTaxLines( + taxLineIds: string[], + sharedContext?: Context + ): Promise + removeShippingMethodTaxLines( + taxLineIds: string, + sharedContext?: Context + ): Promise + removeShippingMethodTaxLines( + selector: Partial, + sharedContext?: Context + ): Promise + + async removeShippingMethodTaxLines( + taxLineIdsOrSelector: + | string + | string[] + | OrderTypes.FilterableOrderShippingMethodTaxLineProps, + @MedusaContext() sharedContext: Context = {} + ): Promise { + let ids: string[] + if (isObject(taxLineIdsOrSelector)) { + const taxLines = await this.listShippingMethodTaxLines( + { + ...(taxLineIdsOrSelector as OrderTypes.FilterableOrderShippingMethodTaxLineProps), + }, + { select: ["id"] }, + sharedContext + ) + + ids = taxLines.map((taxLine) => taxLine.id) + } else { + ids = Array.isArray(taxLineIdsOrSelector) + ? taxLineIdsOrSelector + : [taxLineIdsOrSelector] + } + + await this.shippingMethodTaxLineService_.delete(ids, sharedContext) + } +} diff --git a/packages/order/src/types/UpdateOrderShippingMethodDTO.ts b/packages/order/src/types/UpdateOrderShippingMethodDTO.ts new file mode 100644 index 0000000000..1004d333a8 --- /dev/null +++ b/packages/order/src/types/UpdateOrderShippingMethodDTO.ts @@ -0,0 +1,8 @@ +import { BigNumberInput } from "@medusajs/types" + +export interface UpdateOrderShippingMethodDTO { + id: string + name?: string + amount?: BigNumberInput + data?: Record +} diff --git a/packages/order/src/types/address.ts b/packages/order/src/types/address.ts new file mode 100644 index 0000000000..373fe7d573 --- /dev/null +++ b/packages/order/src/types/address.ts @@ -0,0 +1,20 @@ +export interface UpsertOrderAddressDTO { + customer_id?: string + company?: string + first_name?: string + last_name?: string + address_1?: string + address_2?: string + city?: string + country_code?: string + province?: string + postal_code?: string + phone?: string + metadata?: Record +} + +export interface UpdateOrderAddressDTO extends UpsertOrderAddressDTO { + id: string +} + +export interface CreateOrderAddressDTO extends UpsertOrderAddressDTO {} diff --git a/packages/order/src/types/index.ts b/packages/order/src/types/index.ts new file mode 100644 index 0000000000..7b57d247b9 --- /dev/null +++ b/packages/order/src/types/index.ts @@ -0,0 +1,15 @@ +import { IEventBusModuleService, Logger } from "@medusajs/types" + +export * from "./address" +export * from "./line-item" +export * from "./line-item-adjustment" +export * from "./line-item-tax-line" +export * from "./order" +export * from "./shipping-method" +export * from "./shipping-method-adjustment" +export * from "./shipping-method-tax-line" + +export type InitializeModuleInjectableDependencies = { + logger?: Logger + eventBusService?: IEventBusModuleService +} diff --git a/packages/order/src/types/line-item-adjustment.ts b/packages/order/src/types/line-item-adjustment.ts new file mode 100644 index 0000000000..c7ddd8f201 --- /dev/null +++ b/packages/order/src/types/line-item-adjustment.ts @@ -0,0 +1,15 @@ +import { BigNumberInput } from "@medusajs/types" + +export interface CreateOrderLineItemAdjustmentDTO { + item_id: string + amount: BigNumberInput + code?: string + description?: string + promotion_id?: string + provider_id?: string +} + +export interface UpdateOrderLineItemAdjustmentDTO + extends Partial { + id: string +} diff --git a/packages/order/src/types/line-item-tax-line.ts b/packages/order/src/types/line-item-tax-line.ts new file mode 100644 index 0000000000..ef8f128e20 --- /dev/null +++ b/packages/order/src/types/line-item-tax-line.ts @@ -0,0 +1,9 @@ +import { CreateOrderTaxLineDTO, UpdateOrderTaxLineDTO } from "./tax-line" + +export interface CreateOrderLineItemTaxLineDTO extends CreateOrderTaxLineDTO { + item_id: string +} + +export interface UpdateOrderLineItemTaxLineDTO extends UpdateOrderTaxLineDTO { + item_id: string +} diff --git a/packages/order/src/types/line-item.ts b/packages/order/src/types/line-item.ts new file mode 100644 index 0000000000..fbc87a8b3d --- /dev/null +++ b/packages/order/src/types/line-item.ts @@ -0,0 +1,39 @@ +import { BigNumberInput } from "@medusajs/types" + +interface PartialUpsertOrderLineItemDTO { + subtitle?: string + thumbnail?: string + + product_id?: string + product_title?: string + product_description?: string + product_subtitle?: string + product_type?: string + product_collection?: string + product_handle?: string + + variant_id?: string + variant_sku?: string + variant_barcode?: string + variant_title?: string + variant_option_values?: Record + + requires_shipping?: boolean + is_discountable?: boolean + is_tax_inclusive?: boolean + + compare_at_unit_price?: BigNumberInput +} + +export interface CreateOrderLineItemDTO extends PartialUpsertOrderLineItemDTO { + title: string + quantity: BigNumberInput + unit_price: BigNumberInput + order_id: string +} + +export interface UpdateOrderLineItemDTO + extends PartialUpsertOrderLineItemDTO, + Partial { + id: string +} diff --git a/packages/order/src/types/order.ts b/packages/order/src/types/order.ts new file mode 100644 index 0000000000..562d92bccd --- /dev/null +++ b/packages/order/src/types/order.ts @@ -0,0 +1,33 @@ +import { OrderStatus } from "@medusajs/utils" +import { + CreateOrderLineItemAdjustmentDTO, + UpdateOrderLineItemAdjustmentDTO, +} from "./line-item-adjustment" + +export interface CreateOrderDTO { + region_id?: string + customer_id?: string + sales_channel_id?: string + email?: string + currency_code: string + status?: OrderStatus + no_notification?: boolean + metadata?: Record +} + +export interface UpdateOrderDTO { + id: string + region_id?: string + customer_id?: string + sales_channel_id?: string + email?: string + currency_code?: string + status?: OrderStatus + no_notification?: boolean + metadata?: Record + + adjustments?: ( + | CreateOrderLineItemAdjustmentDTO + | UpdateOrderLineItemAdjustmentDTO + )[] +} diff --git a/packages/order/src/types/shipping-method-adjustment.ts b/packages/order/src/types/shipping-method-adjustment.ts new file mode 100644 index 0000000000..e3651c61bb --- /dev/null +++ b/packages/order/src/types/shipping-method-adjustment.ts @@ -0,0 +1,19 @@ +import { BigNumberInput } from "@medusajs/types" + +export interface CreateOrderShippingMethodAdjustmentDTO { + shipping_method_id: string + code: string + amount: BigNumberInput + description?: string + promotion_id?: string + provider_id?: string +} + +export interface UpdateOrderShippingMethodAdjustmentDTO { + id: string + code?: string + amount?: BigNumberInput + description?: string + promotion_id?: string + provider_id?: string +} diff --git a/packages/order/src/types/shipping-method-tax-line.ts b/packages/order/src/types/shipping-method-tax-line.ts new file mode 100644 index 0000000000..4b75af5d38 --- /dev/null +++ b/packages/order/src/types/shipping-method-tax-line.ts @@ -0,0 +1,11 @@ +import { CreateOrderTaxLineDTO, UpdateOrderTaxLineDTO } from "./tax-line" + +export interface CreateOrderShippingMethodTaxLineDTO + extends CreateOrderTaxLineDTO { + shipping_method_id: string +} + +export interface UpdateOrderShippingMethodTaxLineDTO + extends UpdateOrderTaxLineDTO { + shipping_method_id: string +} diff --git a/packages/order/src/types/shipping-method.ts b/packages/order/src/types/shipping-method.ts new file mode 100644 index 0000000000..4ebed8178b --- /dev/null +++ b/packages/order/src/types/shipping-method.ts @@ -0,0 +1,15 @@ +import { BigNumberInput } from "@medusajs/types" + +export interface CreateOrderShippingMethodDTO { + name: string + shipping_method_id: string + amount: BigNumberInput + data?: Record +} + +export interface UpdateOrderShippingMethodDTO { + id: string + name?: string + amount?: BigNumberInput + data?: Record +} diff --git a/packages/order/src/types/tax-line.ts b/packages/order/src/types/tax-line.ts new file mode 100644 index 0000000000..7fdb8bd27a --- /dev/null +++ b/packages/order/src/types/tax-line.ts @@ -0,0 +1,18 @@ +import { BigNumberInput } from "@medusajs/types" + +export interface UpdateOrderTaxLineDTO { + id: string + description?: string + tax_rate_id?: string + code?: string + rate?: BigNumberInput + provider_id?: string +} + +export interface CreateOrderTaxLineDTO { + description?: string + tax_rate_id?: string + code: string + rate: BigNumberInput + provider_id?: string +} diff --git a/packages/order/tsconfig.json b/packages/order/tsconfig.json new file mode 100644 index 0000000000..4b79cd6032 --- /dev/null +++ b/packages/order/tsconfig.json @@ -0,0 +1,37 @@ +{ + "compilerOptions": { + "lib": ["es2020"], + "target": "es2020", + "outDir": "./dist", + "esModuleInterop": true, + "declaration": true, + "module": "commonjs", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": false, + "noImplicitReturns": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noImplicitThis": true, + "allowJs": true, + "skipLibCheck": true, + "downlevelIteration": true, // to use ES5 specific tooling + "baseUrl": ".", + "resolveJsonModule": true, + "paths": { + "@models": ["./src/models"], + "@services": ["./src/services"], + "@repositories": ["./src/repositories"], + "@types": ["./src/types"] + } + }, + "include": ["src"], + "exclude": [ + "dist", + "./src/**/__tests__", + "./src/**/__mocks__", + "./src/**/__fixtures__", + "node_modules" + ] +} diff --git a/packages/order/tsconfig.spec.json b/packages/order/tsconfig.spec.json new file mode 100644 index 0000000000..48e47e8cbb --- /dev/null +++ b/packages/order/tsconfig.spec.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "include": ["src", "integration-tests"], + "exclude": ["node_modules", "dist"], + "compilerOptions": { + "sourceMap": true + } +} diff --git a/packages/types/src/bundles.ts b/packages/types/src/bundles.ts index d8d91dbc71..ffb500829d 100644 --- a/packages/types/src/bundles.ts +++ b/packages/types/src/bundles.ts @@ -10,6 +10,7 @@ export * as FulfillmentTypes from "./fulfillment" export * as InventoryTypes from "./inventory" export * as LoggerTypes from "./logger" export * as ModulesSdkTypes from "./modules-sdk" +export * as OrderTypes from "./order" export * as PricingTypes from "./pricing" export * as ProductTypes from "./product" export * as PromotionTypes from "./promotion" @@ -20,4 +21,3 @@ export * as StockLocationTypes from "./stock-location" export * as TransactionBaseTypes from "./transaction-base" export * as UserTypes from "./user" export * as WorkflowTypes from "./workflow" - diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index ab086b109d..034b396834 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -8,13 +8,14 @@ export * from "./customer" export * from "./dal" export * from "./event-bus" export * from "./feature-flag" -export * from "./fulfillment" export * from "./file-service" +export * from "./fulfillment" export * from "./inventory" export * from "./joiner" export * from "./link-modules" export * from "./logger" export * from "./modules-sdk" +export * from "./order" export * from "./payment" export * from "./pricing" export * from "./product" @@ -30,4 +31,3 @@ export * from "./totals" export * from "./transaction-base" export * from "./user" export * from "./workflow" - diff --git a/packages/types/src/order/common.ts b/packages/types/src/order/common.ts new file mode 100644 index 0000000000..b695d795ec --- /dev/null +++ b/packages/types/src/order/common.ts @@ -0,0 +1,570 @@ +import { BaseFilterable } from "../dal" +import { OperatorMap } from "../dal/utils" + +export interface OrderAdjustmentLineDTO { + /** + * The ID of the adjustment line + */ + id: string + /** + * The code of the adjustment line + */ + code?: string + /** + * The amount of the adjustment line + */ + amount: number + /** + * The ID of the associated order + */ + order_id: string + /** + * The description of the adjustment line + */ + description?: string + /** + * The ID of the associated promotion + */ + promotion_id?: string + /** + * The ID of the associated provider + */ + provider_id?: string + /** + * When the adjustment line was created + */ + created_at: Date | string + /** + * When the adjustment line was updated + */ + updated_at: Date | string +} + +export interface OrderShippingMethodAdjustmentDTO + extends OrderAdjustmentLineDTO { + /** + * The associated shipping method + */ + shipping_method: OrderShippingMethodDTO + /** + * The ID of the associated shipping method + */ + shipping_method_id: string +} + +export interface OrderLineItemAdjustmentDTO extends OrderAdjustmentLineDTO { + /** + * The associated line item + * @expandable + */ + item: OrderLineItemDTO + /** + * The associated line item + */ + item_id: string +} + +export interface OrderTaxLineDTO { + /** + * The ID of the tax line + */ + id: string + /** + * The description of the tax line + */ + description?: string + /** + * The ID of the associated tax rate + */ + tax_rate_id?: string + /** + * The code of the tax line + */ + code: string + /** + * The rate of the tax line + */ + rate: number + /** + * The ID of the associated provider + */ + provider_id?: string + /** + * When the tax line was created + */ + created_at: Date | string + /** + * When the tax line was updated + */ + updated_at: Date | string +} + +export interface OrderShippingMethodTaxLineDTO extends OrderTaxLineDTO { + /** + * The associated shipping method + */ + shipping_method: OrderShippingMethodDTO + /** + * The ID of the associated shipping method + */ + shipping_method_id: string +} + +export interface OrderLineItemTaxLineDTO extends OrderTaxLineDTO { + /** + * The associated line item + */ + item: OrderLineItemDTO + /** + * The ID of the associated line item + */ + item_id: string +} + +export interface OrderAddressDTO { + /** + * The ID of the address + */ + id: string + /** + * The customer ID of the address + */ + customer_id?: string + /** + * The first name of the address + */ + first_name?: string + /** + * The last name of the address + */ + last_name?: string + /** + * The phone number of the address + */ + phone?: string + /** + * The company of the address + */ + company?: string + /** + * The first address line of the address + */ + address_1?: string + /** + * The second address line of the address + */ + address_2?: string + /** + * The city of the address + */ + city?: string + /** + * The country code of the address + */ + country_code?: string + /** + * The province/state of the address + */ + province?: string + /** + * The postal code of the address + */ + postal_code?: string + /** + * Holds custom data in key-value pairs. + */ + metadata?: Record | null + /** + * When the address was created. + */ + created_at: Date | string + /** + * When the address was updated. + */ + updated_at: Date | string +} + +export interface OrderShippingMethodDTO { + /** + * The ID of the shipping method + */ + id: string + + /** + * The ID of the associated order + */ + order_id: string + + /** + * The name of the shipping method + */ + name: string + /** + * The description of the shipping method + */ + description?: string + + /** + * The price of the shipping method + */ + unit_price: number + + /** + * Whether the shipping method price is tax inclusive or not + */ + is_tax_inclusive: boolean + + /** + * The ID of the shipping option the method was created from + */ + shipping_option_id?: string + + /** + * Additional data needed for fulfillment. + */ + data?: Record + + /** + * Holds custom data in key-value pairs. + */ + metadata?: Record | null + + /** + * The associated tax lines. + * + * @expandable + */ + tax_lines?: OrderShippingMethodTaxLineDTO[] + /** + * The associated adjustments. + * + * @expandable + */ + adjustments?: OrderShippingMethodAdjustmentDTO[] + + /** + * When the shipping method was created. + */ + created_at: Date | string + /** + * When the shipping method was updated. + */ + updated_at: Date | string + + original_total: number + original_subtotal: number + original_tax_total: number + + total: number + subtotal: number + tax_total: number + discount_total: number + discount_tax_total: number +} + +export interface OrderLineItemTotalsDTO { + original_total: number + original_subtotal: number + original_tax_total: number + + item_total: number + item_subtotal: number + item_tax_total: number + + total: number + subtotal: number + tax_total: number + discount_total: number + discount_tax_total: number +} + +export interface OrderLineItemDTO extends OrderLineItemTotalsDTO { + /** + * The ID of the line item. + */ + id: string + /** + * The title of the line item. + */ + title: string + /** + * The subtitle of the line item. + */ + subtitle?: string + /** + * The url of the line item thumbnail. + */ + thumbnail?: string + /** + * The line item quantity + */ + quantity: number + /** + * The product ID of the line item. + */ + product_id?: string + /** + * The product title of the line item. + */ + product_title?: string + /** + * The product description of the line item. + */ + product_description?: string + /** + * The product subtitle of the line item. + */ + product_subtitle?: string + /** + * The product type of the line item. + */ + product_type?: string + /** + * The product collection of the line item. + */ + product_collection?: string + /** + * The product handle of the line item. + */ + product_handle?: string + /** + * The variant ID of the line item. + */ + variant_id?: string + /** + * The variant sku of the line item. + */ + variant_sku?: string + /** + * The variant barcode of the line item. + */ + variant_barcode?: string + /** + * The variant title of the line item. + */ + variant_title?: string + /** + * The variant option values of the line item. + */ + variant_option_values?: Record + /** + * Whether the line item requires shipping or not + */ + requires_shipping: boolean + /** + * Whether the line item is discountable or not + */ + is_discountable: boolean + /** + * Whether the line item price is tax inclusive or not + */ + is_tax_inclusive: boolean + /** + * The original price of the item before an adjustment or a sale. + */ + compare_at_unit_price?: number + /** + * The price of the item + */ + unit_price: number + /** + * The associated tax lines. + * + * @expandable + */ + tax_lines?: OrderLineItemTaxLineDTO[] + /** + * The associated adjustments. + * + * @expandable + */ + adjustments?: OrderLineItemAdjustmentDTO[] + /** + * The associated order. + * + * @expandable + */ + order: OrderDTO + /** + * The ID of the associated order. + */ + order_id: string + /** + * Holds custom data in key-value pairs. + */ + metadata?: Record | null + /** + * When the line item was created. + */ + created_at?: Date + /** + * When the line item was updated. + */ + updated_at?: Date +} + +export interface OrderDTO { + /** + * The ID of the order. + */ + id: string + /** + * The ID of the region the order belongs to. + */ + region_id?: string + /** + * The ID of the customer on the order. + */ + customer_id?: string + /** + * The ID of the sales channel the order belongs to. + */ + sales_channel_id?: string + /** + * The email of the order. + */ + email?: string + /** + * The currency of the order + */ + currency_code: string + /** + * The associated shipping address. + * + * @expandable + */ + shipping_address?: OrderAddressDTO + /** + * The associated billing address. + * + * @expandable + */ + billing_address?: OrderAddressDTO + /** + * The associated line items. + * + * @expandable + */ + items?: OrderLineItemDTO[] + /** + * The associated shipping methods + * + * @expandable + */ + shipping_methods?: OrderShippingMethodDTO[] + /** + * Holds custom data in key-value pairs. + */ + metadata?: Record | null + /** + * When the order was created. + */ + created_at?: string | Date + /** + * When the order was updated. + */ + updated_at?: string | Date + + original_item_total: number + original_item_subtotal: number + original_item_tax_total: number + + item_total: number + item_subtotal: number + item_tax_total: number + + original_total: number + original_subtotal: number + original_tax_total: number + + total: number + subtotal: number + tax_total: number + discount_total: number + raw_discount_total: any + discount_tax_total: number + + gift_card_total: number + gift_card_tax_total: number + + shipping_total: number + shipping_subtotal: number + shipping_tax_total: number + + original_shipping_total: number + original_shipping_subtotal: number + original_shipping_tax_total: number +} + +export interface FilterableOrderProps + extends BaseFilterable { + id?: string | string[] + + sales_channel_id?: string | string[] | OperatorMap + customer_id?: string | string[] | OperatorMap + region_id?: string | string[] | OperatorMap + + created_at?: OperatorMap + updated_at?: OperatorMap +} + +export interface FilterableOrderAddressProps + extends BaseFilterable { + id?: string | string[] +} + +export interface FilterableOrderLineItemProps + extends BaseFilterable { + id?: string | string[] + order_id?: string | string[] + title?: string + variant_id?: string | string[] + product_id?: string | string[] +} + +export interface FilterableOrderLineItemAdjustmentProps + extends BaseFilterable { + id?: string | string[] + item_id?: string | string[] + promotion_id?: string | string[] + provider_id?: string | string[] + item?: FilterableOrderLineItemProps +} +export interface FilterableOrderShippingMethodProps + extends BaseFilterable { + id?: string | string[] + order_id?: string | string[] + name?: string + shipping_option_id?: string | string[] +} + +export interface FilterableOrderShippingMethodAdjustmentProps + extends BaseFilterable { + id?: string | string[] + shipping_method_id?: string | string[] + promotion_id?: string | string[] + provider_id?: string | string[] + shipping_method?: FilterableOrderShippingMethodProps +} + +export interface FilterableOrderLineItemTaxLineProps + extends BaseFilterable { + id?: string | string[] + description?: string + code?: string | string[] + tax_rate_id?: string | string[] + provider_id?: string | string[] + item_id?: string | string[] + item?: FilterableOrderLineItemProps +} + +export interface FilterableOrderShippingMethodTaxLineProps + extends BaseFilterable { + id?: string | string[] + description?: string + code?: string | string[] + tax_rate_id?: string | string[] + provider_id?: string | string[] + shipping_method_id?: string | string[] + shipping_method?: FilterableOrderShippingMethodProps +} diff --git a/packages/types/src/order/index.ts b/packages/types/src/order/index.ts new file mode 100644 index 0000000000..0c73656566 --- /dev/null +++ b/packages/types/src/order/index.ts @@ -0,0 +1,3 @@ +export * from "./common" +export * from "./mutations" +export * from "./service" diff --git a/packages/types/src/order/mutations.ts b/packages/types/src/order/mutations.ts new file mode 100644 index 0000000000..5c7ada5b92 --- /dev/null +++ b/packages/types/src/order/mutations.ts @@ -0,0 +1,241 @@ +import { OrderLineItemDTO } from "./common" + +/** ADDRESS START */ +export interface UpsertOrderAddressDTO { + customer_id?: string + company?: string + first_name?: string + last_name?: string + address_1?: string + address_2?: string + city?: string + country_code?: string + province?: string + postal_code?: string + phone?: string + metadata?: Record +} + +export interface UpdateOrderAddressDTO extends UpsertOrderAddressDTO { + id: string +} + +export interface CreateOrderAddressDTO extends UpsertOrderAddressDTO {} + +/** ADDRESS END */ + +/** ORDER START */ +export interface CreateOrderDTO { + region_id?: string + customer_id?: string + sales_channel_id?: string + status?: string + email?: string + currency_code: string + shipping_address_id?: string + billing_address_id?: string + shipping_address?: CreateOrderAddressDTO | UpdateOrderAddressDTO + billing_address?: CreateOrderAddressDTO | UpdateOrderAddressDTO + no_notification?: boolean + metadata?: Record + + items?: CreateOrderLineItemDTO[] +} + +export interface UpdateOrderDTO { + id: string + region_id?: string + customer_id?: string + sales_channel_id?: string + status?: string + email?: string + currency_code?: string + shipping_address_id?: string + billing_address_id?: string + billing_address?: CreateOrderAddressDTO | UpdateOrderAddressDTO + shipping_address?: CreateOrderAddressDTO | UpdateOrderAddressDTO + no_notification?: boolean + metadata?: Record +} + +/** ORDER END */ + +/** ADJUSTMENT START */ +export interface CreateOrderAdjustmentDTO { + code: string + amount: number + description?: string + promotion_id?: string + provider_id?: string +} + +export interface UpdateOrderAdjustmentDTO { + id: string + code?: string + amount: number + description?: string + promotion_id?: string + provider_id?: string +} + +export interface CreateOrderLineItemAdjustmentDTO + extends CreateOrderAdjustmentDTO { + item_id: string +} + +export interface UpdateOrderLineItemAdjustmentDTO + extends UpdateOrderAdjustmentDTO { + item_id: string +} + +export interface UpsertOrderLineItemAdjustmentDTO { + id?: string + item_id: string + code?: string + amount?: number + description?: string + promotion_id?: string + provider_id?: string +} + +/** ADJUSTMENTS END */ + +/** TAX LINES START */ + +export interface CreateOrderTaxLineDTO { + description?: string + tax_rate_id?: string + code: string + rate: number + provider_id?: string +} + +export interface UpdateOrderTaxLineDTO { + id: string + description?: string + tax_rate_id?: string + code?: string + rate?: number + provider_id?: string +} + +export interface CreateOrderShippingMethodTaxLineDTO + extends CreateOrderTaxLineDTO {} + +export interface UpdateOrderShippingMethodTaxLineDTO + extends UpdateOrderTaxLineDTO {} + +export interface CreateOrderLineItemTaxLineDTO extends CreateOrderTaxLineDTO {} + +export interface UpdateOrderLineItemTaxLineDTO extends UpdateOrderTaxLineDTO {} + +/** TAX LINES END */ + +/** LINE ITEMS START */ +export interface CreateOrderLineItemDTO { + title: string + subtitle?: string + thumbnail?: string + + order_id?: string + + quantity: number + + product_id?: string + product_title?: string + product_description?: string + product_subtitle?: string + product_type?: string + product_collection?: string + product_handle?: string + + variant_id?: string + variant_sku?: string + variant_barcode?: string + variant_title?: string + variant_option_values?: Record + + requires_shipping?: boolean + is_discountable?: boolean + is_tax_inclusive?: boolean + + compare_at_unit_price?: number + unit_price: number | string + + tax_lines?: CreateOrderTaxLineDTO[] + adjustments?: CreateOrderAdjustmentDTO[] +} + +export interface CreateOrderLineItemForOrderDTO extends CreateOrderLineItemDTO { + order_id: string +} + +export interface UpdateOrderLineItemWithSelectorDTO { + selector: Partial + data: Partial +} + +export interface UpdateOrderLineItemDTO + extends Omit< + CreateOrderLineItemDTO, + "tax_lines" | "adjustments" | "title" | "quantity" | "unit_price" + > { + id: string + + title?: string + quantity?: number + unit_price?: number + + tax_lines?: UpdateOrderTaxLineDTO[] | CreateOrderTaxLineDTO[] + adjustments?: UpdateOrderAdjustmentDTO[] | CreateOrderAdjustmentDTO[] +} + +/** LINE ITEMS END */ + +/** SHIPPING METHODS START */ + +export interface CreateOrderShippingMethodDTO { + name: string + order_id: string + amount: number + data?: Record + tax_lines?: CreateOrderTaxLineDTO[] + adjustments?: CreateOrderAdjustmentDTO[] +} + +export interface CreateOrderShippingMethodForSingleOrderDTO { + name: string + amount: number + data?: Record + tax_lines?: CreateOrderTaxLineDTO[] + adjustments?: CreateOrderAdjustmentDTO[] +} + +export interface UpdateOrderShippingMethodDTO { + id: string + name?: string + amount?: number + data?: Record + tax_lines?: UpdateOrderTaxLineDTO[] | CreateOrderTaxLineDTO[] + adjustments?: CreateOrderAdjustmentDTO[] | UpdateOrderAdjustmentDTO[] +} + +export interface CreateOrderShippingMethodAdjustmentDTO { + shipping_method_id: string + code: string + amount: number + description?: string + promotion_id?: string + provider_id?: string +} + +export interface UpdateOrderShippingMethodAdjustmentDTO { + id: string + code?: string + amount?: number + description?: string + promotion_id?: string + provider_id?: string +} + +/** SHIPPING METHODS END */ diff --git a/packages/types/src/order/service.ts b/packages/types/src/order/service.ts new file mode 100644 index 0000000000..cc3027a380 --- /dev/null +++ b/packages/types/src/order/service.ts @@ -0,0 +1,328 @@ +import { FindConfig } from "../common" +import { IModuleService } from "../modules-sdk" +import { Context } from "../shared-context" +import { + FilterableOrderAddressProps, + FilterableOrderLineItemAdjustmentProps, + FilterableOrderLineItemProps, + FilterableOrderLineItemTaxLineProps, + FilterableOrderProps, + FilterableOrderShippingMethodAdjustmentProps, + FilterableOrderShippingMethodProps, + FilterableOrderShippingMethodTaxLineProps, + OrderAddressDTO, + OrderDTO, + OrderLineItemAdjustmentDTO, + OrderLineItemDTO, + OrderLineItemTaxLineDTO, + OrderShippingMethodAdjustmentDTO, + OrderShippingMethodDTO, + OrderShippingMethodTaxLineDTO, +} from "./common" +import { + CreateOrderAddressDTO, + CreateOrderAdjustmentDTO, + CreateOrderDTO, + CreateOrderLineItemDTO, + CreateOrderLineItemForOrderDTO, + CreateOrderLineItemTaxLineDTO, + CreateOrderShippingMethodAdjustmentDTO, + CreateOrderShippingMethodDTO, + CreateOrderShippingMethodForSingleOrderDTO, + CreateOrderShippingMethodTaxLineDTO, + UpdateOrderAddressDTO, + UpdateOrderDTO, + UpdateOrderLineItemDTO, + UpdateOrderLineItemTaxLineDTO, + UpdateOrderLineItemWithSelectorDTO, + UpdateOrderShippingMethodAdjustmentDTO, + UpdateOrderShippingMethodTaxLineDTO, + UpsertOrderLineItemAdjustmentDTO, +} from "./mutations" + +export interface IOrderModuleService extends IModuleService { + retrieve( + orderId: string, + config?: FindConfig, + sharedContext?: Context + ): Promise + + list( + filters?: FilterableOrderProps, + config?: FindConfig, + sharedContext?: Context + ): Promise + + listAndCount( + filters?: FilterableOrderProps, + config?: FindConfig, + sharedContext?: Context + ): Promise<[OrderDTO[], number]> + + create(data: CreateOrderDTO[], sharedContext?: Context): Promise + create(data: CreateOrderDTO, sharedContext?: Context): Promise + + update(data: UpdateOrderDTO[], sharedContext?: Context): Promise + update(data: UpdateOrderDTO, sharedContext?: Context): Promise + + delete(orderIds: string[], sharedContext?: Context): Promise + delete(orderId: string, sharedContext?: Context): Promise + + listAddresses( + filters?: FilterableOrderAddressProps, + config?: FindConfig, + sharedContext?: Context + ): Promise + + createAddresses( + data: CreateOrderAddressDTO[], + sharedContext?: Context + ): Promise + createAddresses( + data: CreateOrderAddressDTO, + sharedContext?: Context + ): Promise + + updateAddresses( + data: UpdateOrderAddressDTO[], + sharedContext?: Context + ): Promise + updateAddresses( + data: UpdateOrderAddressDTO, + sharedContext?: Context + ): Promise + + deleteAddresses(ids: string[], sharedContext?: Context): Promise + deleteAddresses(ids: string, sharedContext?: Context): Promise + + retrieveLineItem( + itemId: string, + config?: FindConfig, + sharedContext?: Context + ): Promise + + listLineItems( + filters: FilterableOrderLineItemProps, + config?: FindConfig, + sharedContext?: Context + ): Promise + + addLineItems( + data: CreateOrderLineItemForOrderDTO + ): Promise + addLineItems( + data: CreateOrderLineItemForOrderDTO[] + ): Promise + addLineItems( + orderId: string, + items: CreateOrderLineItemDTO[], + sharedContext?: Context + ): Promise + + updateLineItems( + data: UpdateOrderLineItemWithSelectorDTO[] + ): Promise + updateLineItems( + selector: Partial, + data: Partial, + sharedContext?: Context + ): Promise + updateLineItems( + lineId: string, + data: Partial, + sharedContext?: Context + ): Promise + + removeLineItems(itemIds: string[], sharedContext?: Context): Promise + removeLineItems(itemIds: string, sharedContext?: Context): Promise + removeLineItems( + selector: Partial, + sharedContext?: Context + ): Promise + + listShippingMethods( + filters: FilterableOrderShippingMethodProps, + config: FindConfig, + sharedContext?: Context + ): Promise + + addShippingMethods( + data: CreateOrderShippingMethodDTO + ): Promise + addShippingMethods( + data: CreateOrderShippingMethodDTO[] + ): Promise + addShippingMethods( + orderId: string, + methods: CreateOrderShippingMethodForSingleOrderDTO[], + sharedContext?: Context + ): Promise + + removeShippingMethods( + methodIds: string[], + sharedContext?: Context + ): Promise + removeShippingMethods( + methodIds: string, + sharedContext?: Context + ): Promise + removeShippingMethods( + selector: Partial, + sharedContext?: Context + ): Promise + + listLineItemAdjustments( + filters: FilterableOrderLineItemAdjustmentProps, + config?: FindConfig, + sharedContext?: Context + ): Promise + + addLineItemAdjustments( + data: CreateOrderAdjustmentDTO[] + ): Promise + addLineItemAdjustments( + data: CreateOrderAdjustmentDTO + ): Promise + addLineItemAdjustments( + orderId: string, + data: CreateOrderAdjustmentDTO[] + ): Promise + + setLineItemAdjustments( + orderId: string, + data: UpsertOrderLineItemAdjustmentDTO[], + sharedContext?: Context + ): Promise + + removeLineItemAdjustments( + adjustmentIds: string[], + sharedContext?: Context + ): Promise + removeLineItemAdjustments( + adjustmentIds: string, + sharedContext?: Context + ): Promise + removeLineItemAdjustments( + selector: Partial, + sharedContext?: Context + ): Promise + + listShippingMethodAdjustments( + filters: FilterableOrderShippingMethodAdjustmentProps, + config?: FindConfig, + sharedContext?: Context + ): Promise + + addShippingMethodAdjustments( + data: CreateOrderShippingMethodAdjustmentDTO[] + ): Promise + addShippingMethodAdjustments( + data: CreateOrderShippingMethodAdjustmentDTO + ): Promise + addShippingMethodAdjustments( + orderId: string, + data: CreateOrderShippingMethodAdjustmentDTO[], + sharedContext?: Context + ): Promise + + setShippingMethodAdjustments( + orderId: string, + data: ( + | CreateOrderShippingMethodAdjustmentDTO + | UpdateOrderShippingMethodAdjustmentDTO + )[], + sharedContext?: Context + ): Promise + + removeShippingMethodAdjustments( + adjustmentIds: string[], + sharedContext?: Context + ): Promise + removeShippingMethodAdjustments( + adjustmentId: string, + sharedContext?: Context + ): Promise + removeShippingMethodAdjustments( + selector: Partial, + sharedContext?: Context + ): Promise + + listLineItemTaxLines( + filters: FilterableOrderLineItemTaxLineProps, + config?: FindConfig, + sharedContext?: Context + ): Promise + + addLineItemTaxLines( + taxLines: CreateOrderLineItemTaxLineDTO[] + ): Promise + addLineItemTaxLines( + taxLine: CreateOrderLineItemTaxLineDTO + ): Promise + addLineItemTaxLines( + orderId: string, + taxLines: CreateOrderLineItemTaxLineDTO[] | CreateOrderLineItemTaxLineDTO, + sharedContext?: Context + ): Promise + + setLineItemTaxLines( + orderId: string, + taxLines: (CreateOrderLineItemTaxLineDTO | UpdateOrderLineItemTaxLineDTO)[], + sharedContext?: Context + ): Promise + + removeLineItemTaxLines( + taxLineIds: string[], + sharedContext?: Context + ): Promise + removeLineItemTaxLines( + taxLineIds: string, + sharedContext?: Context + ): Promise + removeLineItemTaxLines( + selector: FilterableOrderLineItemTaxLineProps, + sharedContext?: Context + ): Promise + + listShippingMethodTaxLines( + filters: FilterableOrderShippingMethodTaxLineProps, + config?: FindConfig, + sharedContext?: Context + ): Promise + + addShippingMethodTaxLines( + taxLines: CreateOrderShippingMethodTaxLineDTO[] + ): Promise + addShippingMethodTaxLines( + taxLine: CreateOrderShippingMethodTaxLineDTO + ): Promise + addShippingMethodTaxLines( + orderId: string, + taxLines: + | CreateOrderShippingMethodTaxLineDTO[] + | CreateOrderShippingMethodTaxLineDTO, + sharedContext?: Context + ): Promise + + setShippingMethodTaxLines( + orderId: string, + taxLines: ( + | CreateOrderShippingMethodTaxLineDTO + | UpdateOrderShippingMethodTaxLineDTO + )[], + sharedContext?: Context + ): Promise + + removeShippingMethodTaxLines( + taxLineIds: string[], + sharedContext?: Context + ): Promise + removeShippingMethodTaxLines( + taxLineIds: string, + sharedContext?: Context + ): Promise + removeShippingMethodTaxLines( + selector: FilterableOrderShippingMethodTaxLineProps, + sharedContext?: Context + ): Promise +} diff --git a/packages/types/src/totals/big-number.ts b/packages/types/src/totals/big-number.ts index 1a0740d154..e6ef0dbaa1 100644 --- a/packages/types/src/totals/big-number.ts +++ b/packages/types/src/totals/big-number.ts @@ -5,8 +5,4 @@ export type BigNumberRawValue = { [key: string]: unknown } -export type BigNumberRawPriceInput = - | BigNumberRawValue - | number - | string - | BigNumber +export type BigNumberInput = BigNumberRawValue | number | string | BigNumber diff --git a/packages/user/src/models/invite.ts b/packages/user/src/models/invite.ts index de8ba28243..12661b57f8 100644 --- a/packages/user/src/models/invite.ts +++ b/packages/user/src/models/invite.ts @@ -1,20 +1,20 @@ import { BeforeCreate, Entity, + Filter, + Index, OnInit, + OptionalProps, PrimaryKey, Property, - Index, - Filter, - OptionalProps, } from "@mikro-orm/core" +import { DAL } from "@medusajs/types" import { DALUtils, - generateEntityId, createPsqlIndexStatementHelper, + generateEntityId, } from "@medusajs/utils" -import { DAL } from "@medusajs/types" const inviteEmailIndexName = "IDX_invite_email" const inviteEmailIndexStatement = createPsqlIndexStatementHelper({ @@ -23,7 +23,7 @@ const inviteEmailIndexStatement = createPsqlIndexStatementHelper({ columns: "email", where: "deleted_at IS NULL", unique: true, -}) +}).expression const inviteTokenIndexName = "IDX_invite_token" const inviteTokenIndexStatement = createPsqlIndexStatementHelper({ @@ -31,7 +31,7 @@ const inviteTokenIndexStatement = createPsqlIndexStatementHelper({ tableName: "invite", columns: "token", where: "deleted_at IS NULL", -}) +}).expression const inviteDeletedAtIndexName = "IDX_invite_deleted_at" const inviteDeletedAtIndexStatement = createPsqlIndexStatementHelper({ @@ -39,7 +39,7 @@ const inviteDeletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "invite", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression type OptionalFields = | "metadata" diff --git a/packages/user/src/models/user.ts b/packages/user/src/models/user.ts index c31d7c0d47..dd4882cefc 100644 --- a/packages/user/src/models/user.ts +++ b/packages/user/src/models/user.ts @@ -1,17 +1,20 @@ import { BeforeCreate, Entity, + Filter, + Index, OnInit, + OptionalProps, PrimaryKey, Property, - Index, - OptionalProps, - Filter, } from "@mikro-orm/core" -import { DALUtils, generateEntityId } from "@medusajs/utils" import { DAL } from "@medusajs/types" -import { createPsqlIndexStatementHelper } from "@medusajs/utils" +import { + DALUtils, + createPsqlIndexStatementHelper, + generateEntityId, +} from "@medusajs/utils" const userEmailIndexName = "IDX_user_email" const userEmailIndexStatement = createPsqlIndexStatementHelper({ @@ -19,7 +22,7 @@ const userEmailIndexStatement = createPsqlIndexStatementHelper({ tableName: "user", columns: "email", where: "deleted_at IS NULL", -}) +}).expression const userDeletedAtIndexName = "IDX_user_deleted_at" const userDeletedAtIndexStatement = createPsqlIndexStatementHelper({ @@ -27,7 +30,7 @@ const userDeletedAtIndexStatement = createPsqlIndexStatementHelper({ tableName: "user", columns: "deleted_at", where: "deleted_at IS NOT NULL", -}) +}).expression type OptionalFields = | "first_name" diff --git a/packages/utils/src/bundles.ts b/packages/utils/src/bundles.ts index 2279b1fe14..15b6a512e2 100644 --- a/packages/utils/src/bundles.ts +++ b/packages/utils/src/bundles.ts @@ -6,6 +6,7 @@ export * as FeatureFlagUtils from "./feature-flags" export * as FulfillmentUtils from "./fulfillment" export * as ModulesSdkUtils from "./modules-sdk" export * as OrchestrationUtils from "./orchestration" +export * as OrderUtils from "./order" export * as ProductUtils from "./product" export * as PromotionUtils from "./promotion" export * as SearchUtils from "./search" diff --git a/packages/utils/src/common/__tests__/create-psql-index-helper.ts b/packages/utils/src/common/__tests__/create-psql-index-helper.ts index 321e87c913..aea4935874 100644 --- a/packages/utils/src/common/__tests__/create-psql-index-helper.ts +++ b/packages/utils/src/common/__tests__/create-psql-index-helper.ts @@ -9,11 +9,23 @@ describe("createPsqlIndexStatementHelper", function () { } const indexStatement = createPsqlIndexStatementHelper(options) - expect(indexStatement).toEqual( + expect(indexStatement + "").toEqual( `CREATE INDEX IF NOT EXISTS "${options.name}" ON "${options.tableName}" (${options.columns})` ) }) + it("should generate a simple index and auto compose its name", function () { + const options = { + tableName: "table_name", + columns: "column_name", + } + + const indexStatement = createPsqlIndexStatementHelper(options) + expect(indexStatement + "").toEqual( + `CREATE INDEX IF NOT EXISTS "IDX_table_name_column_name" ON "${options.tableName}" (${options.columns})` + ) + }) + it("should generate a composite index", function () { const options = { name: "index_name", @@ -22,7 +34,7 @@ describe("createPsqlIndexStatementHelper", function () { } const indexStatement = createPsqlIndexStatementHelper(options) - expect(indexStatement).toEqual( + expect(indexStatement.expression).toEqual( `CREATE INDEX IF NOT EXISTS "${options.name}" ON "${ options.tableName }" (${options.columns.join(", ")})` @@ -38,7 +50,7 @@ describe("createPsqlIndexStatementHelper", function () { } const indexStatement = createPsqlIndexStatementHelper(options) - expect(indexStatement).toEqual( + expect(indexStatement.expression).toEqual( `CREATE INDEX IF NOT EXISTS "${options.name}" ON "${ options.tableName }" (${options.columns.join(", ")}) WHERE ${options.where}` @@ -55,7 +67,7 @@ describe("createPsqlIndexStatementHelper", function () { } const indexStatement = createPsqlIndexStatementHelper(options) - expect(indexStatement).toEqual( + expect(indexStatement.toString()).toEqual( `CREATE INDEX IF NOT EXISTS "${options.name}" ON "${ options.tableName }" USING GIN (${options.columns.join(", ")}) WHERE ${options.where}` @@ -64,7 +76,6 @@ describe("createPsqlIndexStatementHelper", function () { it("should generate unique constraint", function () { const options = { - name: "index_name", tableName: "table_name", columns: ["column_name_1", "column_name_2"], unique: true, @@ -72,8 +83,8 @@ describe("createPsqlIndexStatementHelper", function () { } const indexStatement = createPsqlIndexStatementHelper(options) - expect(indexStatement).toEqual( - `CREATE UNIQUE INDEX IF NOT EXISTS "${options.name}" ON "${ + expect(indexStatement.expression).toEqual( + `CREATE UNIQUE INDEX IF NOT EXISTS "IDX_table_name_column_name_1_column_name_2" ON "${ options.tableName }" (${options.columns.join(", ")}) WHERE ${options.where}` ) diff --git a/packages/utils/src/common/create-psql-index-helper.ts b/packages/utils/src/common/create-psql-index-helper.ts index f482bd3606..47852b8862 100644 --- a/packages/utils/src/common/create-psql-index-helper.ts +++ b/packages/utils/src/common/create-psql-index-helper.ts @@ -1,6 +1,8 @@ +import { Index } from "@mikro-orm/core" + /** * Create a PSQL index statement - * @param name The name of the index + * @param name The name of the index, if not provided it will be generated in the format IDX_tableName_columnName * @param tableName The name of the table * @param columns The columns to index * @param type The type of index (e.g GIN, GIST, BTREE, etc) @@ -16,7 +18,7 @@ * where: "email IS NOT NULL" * }); * - * // CREATE INDEX IF NOT EXISTS idx_user_email ON user USING btree (email) WHERE email IS NOT NULL; + * // expression: CREATE INDEX IF NOT EXISTS idx_user_email ON user USING btree (email) WHERE email IS NOT NULL; * * createPsqlIndexStatementHelper({ * name: "idx_user_email", @@ -24,7 +26,7 @@ * columns: "email" * }); * - * // CREATE INDEX IF NOT EXISTS idx_user_email ON user (email); + * // expression: CREATE INDEX IF NOT EXISTS idx_user_email ON user (email); * */ export function createPsqlIndexStatementHelper({ @@ -35,17 +37,38 @@ export function createPsqlIndexStatementHelper({ where, unique, }: { - name: string + name?: string tableName: string columns: string | string[] type?: string where?: string unique?: boolean }) { + const columnsName = Array.isArray(columns) ? columns.join("_") : columns + columns = Array.isArray(columns) ? columns.join(", ") : columns + name = name || `IDX_${tableName}_${columnsName}` + const typeStr = type ? ` USING ${type}` : "" const optionsStr = where ? ` WHERE ${where}` : "" const uniqueStr = unique ? "UNIQUE " : "" - return `CREATE ${uniqueStr}INDEX IF NOT EXISTS "${name}" ON "${tableName}"${typeStr} (${columns})${optionsStr}` + const expression = `CREATE ${uniqueStr}INDEX IF NOT EXISTS "${name}" ON "${tableName}"${typeStr} (${columns})${optionsStr}` + return { + toString: () => { + return expression + }, + valueOf: () => { + return expression + }, + name, + expression, + MikroORMIndex: (options = {}) => { + return Index({ + name, + expression, + ...options, + }) + }, + } } diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index bf8953ef38..6dea3aa212 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -10,6 +10,7 @@ export * from "./feature-flags" export * from "./fulfillment" export * from "./modules-sdk" export * from "./orchestration" +export * from "./order" export * from "./payment" export * from "./pricing" export * from "./product" diff --git a/packages/utils/src/order/index.ts b/packages/utils/src/order/index.ts new file mode 100644 index 0000000000..acdaf2e2da --- /dev/null +++ b/packages/utils/src/order/index.ts @@ -0,0 +1 @@ +export * from "./status" diff --git a/packages/utils/src/order/status.ts b/packages/utils/src/order/status.ts new file mode 100644 index 0000000000..8ed93b743e --- /dev/null +++ b/packages/utils/src/order/status.ts @@ -0,0 +1,31 @@ +/** + * @enum + * + * The order's status. + */ +export enum OrderStatus { + /** + * The order is pending. + */ + PENDING = "pending", + /** + * The order is completed + */ + COMPLETED = "completed", + /** + * The order is a draft. + */ + DRAFT = "draft", + /** + * The order is archived. + */ + ARCHIVED = "archived", + /** + * The order is canceled. + */ + CANCELED = "canceled", + /** + * The order requires action. + */ + REQUIRES_ACTION = "requires_action", +} diff --git a/packages/utils/src/totals/big-number.ts b/packages/utils/src/totals/big-number.ts index 623d967eff..c7a39a4e08 100644 --- a/packages/utils/src/totals/big-number.ts +++ b/packages/utils/src/totals/big-number.ts @@ -1,4 +1,4 @@ -import { BigNumberRawPriceInput, BigNumberRawValue } from "@medusajs/types" +import { BigNumberInput, BigNumberRawValue } from "@medusajs/types" import { BigNumber as BigNumberJS } from "bignumber.js" import { isBigNumber, isString } from "../common" @@ -8,11 +8,11 @@ export class BigNumber { private numeric_: number private raw_?: BigNumberRawValue - constructor(rawPrice: BigNumberRawPriceInput) { + constructor(rawPrice: BigNumberInput) { this.setRawPriceOrThrow(rawPrice) } - setRawPriceOrThrow(rawPrice: BigNumberRawPriceInput) { + setRawPriceOrThrow(rawPrice: BigNumberInput) { if (BigNumberJS.isBigNumber(rawPrice)) { /** * Example: @@ -67,7 +67,7 @@ export class BigNumber { } } - set numeric(value: BigNumberRawPriceInput) { + set numeric(value: BigNumberInput) { const newValue = new BigNumber(value) this.numeric_ = newValue.numeric_ this.raw_ = newValue.raw_ @@ -77,7 +77,7 @@ export class BigNumber { return this.raw_ } - set raw(rawValue: BigNumberRawPriceInput) { + set raw(rawValue: BigNumberInput) { const newValue = new BigNumber(rawValue) this.numeric_ = newValue.numeric_ this.raw_ = newValue.raw_ diff --git a/packages/utils/src/totals/to-big-number-js.ts b/packages/utils/src/totals/to-big-number-js.ts index 15c2721383..d3e94467e5 100644 --- a/packages/utils/src/totals/to-big-number-js.ts +++ b/packages/utils/src/totals/to-big-number-js.ts @@ -1,4 +1,4 @@ -import { BigNumberRawPriceInput } from "@medusajs/types" +import { BigNumberInput } from "@medusajs/types" import { BigNumber as BigNumberJs } from "bignumber.js" import { isDefined, toCamelCase } from "../common" import { BigNumber } from "./big-number" @@ -18,7 +18,7 @@ export function toBigNumberJs( ): Output { return fields.reduce((acc, field: string) => { const camelCased = toCamelCase(field) - let val: BigNumberRawPriceInput = 0 + let val: BigNumberInput = 0 if (isDefined(entity[field])) { const entityField = entity[field] diff --git a/yarn.lock b/yarn.lock index e0a090f86c..5fdabe2bb1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8494,6 +8494,33 @@ __metadata: languageName: unknown linkType: soft +"@medusajs/order@workspace:packages/order": + version: 0.0.0-use.local + resolution: "@medusajs/order@workspace:packages/order" + dependencies: + "@medusajs/modules-sdk": ^1.12.4 + "@medusajs/types": ^1.11.8 + "@medusajs/utils": ^1.11.1 + "@mikro-orm/cli": 5.9.7 + "@mikro-orm/core": 5.9.7 + "@mikro-orm/migrations": 5.9.7 + "@mikro-orm/postgresql": 5.9.7 + awilix: ^8.0.0 + cross-env: ^5.2.1 + dotenv: ^16.1.4 + jest: ^29.6.3 + knex: 2.4.2 + medusa-test-utils: ^1.1.40 + rimraf: ^3.0.2 + ts-jest: ^29.1.1 + ts-node: ^10.9.1 + tsc-alias: ^1.8.6 + typescript: ^5.1.6 + bin: + medusa-order-seed: dist/scripts/bin/run-seed.js + languageName: unknown + linkType: soft + "@medusajs/payment@workspace:packages/payment": version: 0.0.0-use.local resolution: "@medusajs/payment@workspace:packages/payment"