feat: Line Items API Routes (#6478)
**What** - `POST /store/carts/:id/line-items` - `POST /store/carts/:id/line-items/:id` - `DELETE /store/carts/:id/line-items/:id` **Outstanding** - Integration tests - Module integrations: Payment, Fulfillment, Promotions Depends on #6475 and #6449.
This commit is contained in:
1 parent
f5c2256286
commit
3ee0f599c1
30 files changed
+936
-207
No files matched your search
@@ -1,7 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
addToCartWorkflow,
|
addToCartWorkflow,
|
||||||
createCartWorkflow,
|
createCartWorkflow,
|
||||||
|
|
||||||
|
deleteLineItemsStepId,
|
||||||
|
deleteLineItemsWorkflow,
|
||||||
findOrCreateCustomerStepId,
|
findOrCreateCustomerStepId,
|
||||||
|
updateLineItemInCartWorkflow,
|
||||||
|
updateLineItemsStepId,
|
||||||
} from "@medusajs/core-flows"
|
} from "@medusajs/core-flows"
|
||||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
import {
|
import {
|
||||||
@@ -409,4 +414,260 @@ describe("Carts workflows", () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("updateLineItemInCartWorkflow", () => {
|
||||||
|
it("should update item in cart", async () => {
|
||||||
|
const [product] = await productModule.create([
|
||||||
|
{
|
||||||
|
title: "Test product",
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
title: "Test variant",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const priceSet = await pricingModule.create({
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
amount: 3000,
|
||||||
|
currency_code: "usd",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
await remoteLink.create([
|
||||||
|
{
|
||||||
|
productService: {
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
},
|
||||||
|
pricingService: {
|
||||||
|
price_set_id: priceSet.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
let cart = await cartModuleService.create({
|
||||||
|
currency_code: "usd",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
unit_price: 5000,
|
||||||
|
title: "Test item",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
cart = await cartModuleService.retrieve(cart.id, {
|
||||||
|
select: ["id", "region_id", "currency_code"],
|
||||||
|
relations: ["items", "items.variant_id", "items.metadata"],
|
||||||
|
})
|
||||||
|
|
||||||
|
const item = cart.items?.[0]!
|
||||||
|
|
||||||
|
await updateLineItemInCartWorkflow(appContainer).run({
|
||||||
|
input: {
|
||||||
|
cart,
|
||||||
|
item,
|
||||||
|
update: {
|
||||||
|
metadata: {
|
||||||
|
foo: "bar",
|
||||||
|
},
|
||||||
|
quantity: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const updatedItem = await cartModuleService.retrieveLineItem(item.id)
|
||||||
|
|
||||||
|
expect(updatedItem).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: item.id,
|
||||||
|
unit_price: 3000,
|
||||||
|
quantity: 2,
|
||||||
|
title: "Test item",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("compensation", () => {
|
||||||
|
it("should revert line item update to original state", async () => {
|
||||||
|
expect.assertions(2)
|
||||||
|
const workflow = updateLineItemInCartWorkflow(appContainer)
|
||||||
|
|
||||||
|
workflow.appendAction("throw", updateLineItemsStepId, {
|
||||||
|
invoke: async function failStep() {
|
||||||
|
throw new Error(`Failed to update something after line items`)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const [product] = await productModule.create([
|
||||||
|
{
|
||||||
|
title: "Test product",
|
||||||
|
variants: [
|
||||||
|
{
|
||||||
|
title: "Test variant",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
let cart = await cartModuleService.create({
|
||||||
|
currency_code: "usd",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
unit_price: 3000,
|
||||||
|
title: "Test item",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const priceSet = await pricingModule.create({
|
||||||
|
prices: [
|
||||||
|
{
|
||||||
|
amount: 5000,
|
||||||
|
currency_code: "usd",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
await remoteLink.create([
|
||||||
|
{
|
||||||
|
productService: {
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
},
|
||||||
|
pricingService: {
|
||||||
|
price_set_id: priceSet.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
cart = await cartModuleService.retrieve(cart.id, {
|
||||||
|
select: ["id", "region_id", "currency_code"],
|
||||||
|
relations: ["items", "items.variant_id", "items.metadata"],
|
||||||
|
})
|
||||||
|
|
||||||
|
const item = cart.items?.[0]!
|
||||||
|
|
||||||
|
const { errors } = await workflow.run({
|
||||||
|
input: {
|
||||||
|
cart,
|
||||||
|
item,
|
||||||
|
update: {
|
||||||
|
metadata: {
|
||||||
|
foo: "bar",
|
||||||
|
},
|
||||||
|
title: "Test item updated",
|
||||||
|
quantity: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(errors).toEqual([
|
||||||
|
{
|
||||||
|
action: "throw",
|
||||||
|
handlerType: "invoke",
|
||||||
|
error: new Error(`Failed to update something after line items`),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const updatedItem = await cartModuleService.retrieveLineItem(item.id)
|
||||||
|
|
||||||
|
expect(updatedItem).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: item.id,
|
||||||
|
unit_price: 3000,
|
||||||
|
quantity: 1,
|
||||||
|
title: "Test item",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("deleteLineItems", () => {
|
||||||
|
it("should delete items in cart", async () => {
|
||||||
|
const cart = await cartModuleService.create({
|
||||||
|
currency_code: "usd",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
quantity: 1,
|
||||||
|
unit_price: 5000,
|
||||||
|
title: "Test item",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const items = await cartModuleService.listLineItems({ cart_id: cart.id })
|
||||||
|
|
||||||
|
await deleteLineItemsWorkflow(appContainer).run({
|
||||||
|
input: {
|
||||||
|
ids: items.map((i) => i.id),
|
||||||
|
},
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const [deletedItem] = await cartModuleService.listLineItems({
|
||||||
|
id: items.map((i) => i.id),
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(deletedItem).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("compensation", () => {
|
||||||
|
it("should restore line item if delete fails", async () => {
|
||||||
|
const workflow = deleteLineItemsWorkflow(appContainer)
|
||||||
|
|
||||||
|
workflow.appendAction("throw", deleteLineItemsStepId, {
|
||||||
|
invoke: async function failStep() {
|
||||||
|
throw new Error(`Failed to do something after deleting line items`)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const cart = await cartModuleService.create({
|
||||||
|
currency_code: "usd",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
quantity: 1,
|
||||||
|
unit_price: 3000,
|
||||||
|
title: "Test item",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const items = await cartModuleService.listLineItems({
|
||||||
|
cart_id: cart.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { errors } = await workflow.run({
|
||||||
|
input: {
|
||||||
|
ids: items.map((i) => i.id),
|
||||||
|
},
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(errors).toEqual([
|
||||||
|
{
|
||||||
|
action: "throw",
|
||||||
|
handlerType: "invoke",
|
||||||
|
error: new Error(
|
||||||
|
`Failed to do something after deleting line items`
|
||||||
|
),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const updatedItem = await cartModuleService.retrieveLineItem(
|
||||||
|
items[0].id
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(updatedItem).not.toBeUndefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
@@ -658,6 +658,15 @@
|
|||||||
"nullable": false,
|
"nullable": false,
|
||||||
"mappedType": "json"
|
"mappedType": "json"
|
||||||
},
|
},
|
||||||
|
"metadata": {
|
||||||
|
"name": "metadata",
|
||||||
|
"type": "jsonb",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"mappedType": "json"
|
||||||
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"name": "created_at",
|
"name": "created_at",
|
||||||
"type": "timestamptz",
|
"type": "timestamptz",
|
||||||
@@ -798,6 +807,15 @@
|
|||||||
"nullable": false,
|
"nullable": false,
|
||||||
"mappedType": "decimal"
|
"mappedType": "decimal"
|
||||||
},
|
},
|
||||||
|
"raw_amount": {
|
||||||
|
"name": "raw_amount",
|
||||||
|
"type": "jsonb",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "json"
|
||||||
|
},
|
||||||
"provider_id": {
|
"provider_id": {
|
||||||
"name": "provider_id",
|
"name": "provider_id",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -807,6 +825,15 @@
|
|||||||
"nullable": true,
|
"nullable": true,
|
||||||
"mappedType": "text"
|
"mappedType": "text"
|
||||||
},
|
},
|
||||||
|
"metadata": {
|
||||||
|
"name": "metadata",
|
||||||
|
"type": "jsonb",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"mappedType": "json"
|
||||||
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"name": "created_at",
|
"name": "created_at",
|
||||||
"type": "timestamptz",
|
"type": "timestamptz",
|
||||||
@@ -957,6 +984,15 @@
|
|||||||
"nullable": true,
|
"nullable": true,
|
||||||
"mappedType": "text"
|
"mappedType": "text"
|
||||||
},
|
},
|
||||||
|
"metadata": {
|
||||||
|
"name": "metadata",
|
||||||
|
"type": "jsonb",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"mappedType": "json"
|
||||||
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"name": "created_at",
|
"name": "created_at",
|
||||||
"type": "timestamptz",
|
"type": "timestamptz",
|
||||||
@@ -1283,6 +1319,15 @@
|
|||||||
"nullable": false,
|
"nullable": false,
|
||||||
"mappedType": "decimal"
|
"mappedType": "decimal"
|
||||||
},
|
},
|
||||||
|
"raw_amount": {
|
||||||
|
"name": "raw_amount",
|
||||||
|
"type": "jsonb",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": false,
|
||||||
|
"mappedType": "json"
|
||||||
|
},
|
||||||
"provider_id": {
|
"provider_id": {
|
||||||
"name": "provider_id",
|
"name": "provider_id",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -1323,6 +1368,15 @@
|
|||||||
"nullable": false,
|
"nullable": false,
|
||||||
"mappedType": "text"
|
"mappedType": "text"
|
||||||
},
|
},
|
||||||
|
"metadata": {
|
||||||
|
"name": "metadata",
|
||||||
|
"type": "jsonb",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"mappedType": "json"
|
||||||
|
},
|
||||||
"promotion_id": {
|
"promotion_id": {
|
||||||
"name": "promotion_id",
|
"name": "promotion_id",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -1436,6 +1490,15 @@
|
|||||||
"nullable": true,
|
"nullable": true,
|
||||||
"mappedType": "text"
|
"mappedType": "text"
|
||||||
},
|
},
|
||||||
|
"metadata": {
|
||||||
|
"name": "metadata",
|
||||||
|
"type": "jsonb",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"mappedType": "json"
|
||||||
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"name": "created_at",
|
"name": "created_at",
|
||||||
"type": "timestamptz",
|
"type": "timestamptz",
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ export class Migration20240222170223 extends Migration {
|
|||||||
"raw_compare_at_unit_price" JSONB NULL,
|
"raw_compare_at_unit_price" JSONB NULL,
|
||||||
"unit_price" NUMERIC NOT NULL,
|
"unit_price" NUMERIC NOT NULL,
|
||||||
"raw_unit_price" JSONB NOT NULL,
|
"raw_unit_price" JSONB NOT NULL,
|
||||||
|
"metadata" JSONB NULL,
|
||||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"deleted_at" TIMESTAMPTZ NULL,
|
"deleted_at" TIMESTAMPTZ NULL,
|
||||||
@@ -106,7 +107,9 @@ export class Migration20240222170223 extends Migration {
|
|||||||
"promotion_id" TEXT NULL,
|
"promotion_id" TEXT NULL,
|
||||||
"code" TEXT NULL,
|
"code" TEXT NULL,
|
||||||
"amount" NUMERIC NOT NULL,
|
"amount" NUMERIC NOT NULL,
|
||||||
|
"raw_amount" JSONB NOT NULL,
|
||||||
"provider_id" TEXT NULL,
|
"provider_id" TEXT NULL,
|
||||||
|
"metadata" JSONB NULL,
|
||||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"deleted_at" TIMESTAMPTZ NULL,
|
"deleted_at" TIMESTAMPTZ NULL,
|
||||||
@@ -125,6 +128,7 @@ export class Migration20240222170223 extends Migration {
|
|||||||
"code" TEXT NOT NULL,
|
"code" TEXT NOT NULL,
|
||||||
"rate" NUMERIC NOT NULL,
|
"rate" NUMERIC NOT NULL,
|
||||||
"provider_id" TEXT NULL,
|
"provider_id" TEXT NULL,
|
||||||
|
"metadata" JSONB NULL,
|
||||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"deleted_at" TIMESTAMPTZ NULL,
|
"deleted_at" TIMESTAMPTZ NULL,
|
||||||
@@ -162,7 +166,9 @@ export class Migration20240222170223 extends Migration {
|
|||||||
"promotion_id" TEXT NULL,
|
"promotion_id" TEXT NULL,
|
||||||
"code" TEXT NULL,
|
"code" TEXT NULL,
|
||||||
"amount" NUMERIC NOT NULL,
|
"amount" NUMERIC NOT NULL,
|
||||||
|
"raw_amount" JSONB NOT NULL,
|
||||||
"provider_id" TEXT NULL,
|
"provider_id" TEXT NULL,
|
||||||
|
"metadata" JSONB NULL,
|
||||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"deleted_at" TIMESTAMPTZ NULL,
|
"deleted_at" TIMESTAMPTZ NULL,
|
||||||
@@ -180,6 +186,7 @@ export class Migration20240222170223 extends Migration {
|
|||||||
"code" TEXT NOT NULL,
|
"code" TEXT NOT NULL,
|
||||||
"rate" NUMERIC NOT NULL,
|
"rate" NUMERIC NOT NULL,
|
||||||
"provider_id" TEXT NULL,
|
"provider_id" TEXT NULL,
|
||||||
|
"metadata" JSONB NULL,
|
||||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"deleted_at" TIMESTAMPTZ NULL,
|
"deleted_at" TIMESTAMPTZ NULL,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { DAL } from "@medusajs/types"
|
import { DAL } from "@medusajs/types"
|
||||||
|
import { BigNumber, MikroOrmBigNumberProperty } from "@medusajs/utils"
|
||||||
import { OptionalProps, PrimaryKey, Property } from "@mikro-orm/core"
|
import { OptionalProps, PrimaryKey, Property } from "@mikro-orm/core"
|
||||||
|
|
||||||
type OptionalAdjustmentLineProps = DAL.SoftDeletableEntityDateColumns
|
type OptionalAdjustmentLineProps = DAL.SoftDeletableEntityDateColumns
|
||||||
@@ -19,12 +20,18 @@ export default abstract class AdjustmentLine {
|
|||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
code: string | null = null
|
code: string | null = null
|
||||||
|
|
||||||
@Property({ columnType: "numeric", serializer: Number })
|
@MikroOrmBigNumberProperty()
|
||||||
amount: number
|
amount: BigNumber | number
|
||||||
|
|
||||||
|
@Property({ columnType: "jsonb" })
|
||||||
|
raw_amount: Record<string, unknown>
|
||||||
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
provider_id: string | null = null
|
provider_id: string | null = null
|
||||||
|
|
||||||
|
@Property({ columnType: "jsonb", nullable: true })
|
||||||
|
metadata: Record<string, unknown> | null = null
|
||||||
|
|
||||||
@Property({
|
@Property({
|
||||||
onCreate: () => new Date(),
|
onCreate: () => new Date(),
|
||||||
columnType: "timestamptz",
|
columnType: "timestamptz",
|
||||||
|
|||||||
@@ -26,6 +26,54 @@ type OptionalCartProps =
|
|||||||
| "billing_address"
|
| "billing_address"
|
||||||
| DAL.SoftDeletableEntityDateColumns
|
| DAL.SoftDeletableEntityDateColumns
|
||||||
|
|
||||||
|
const RegionIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_cart_region_id",
|
||||||
|
tableName: "cart",
|
||||||
|
columns: "region_id",
|
||||||
|
where: "deleted_at IS NULL AND region_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const CustomerIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_cart_customer_id",
|
||||||
|
tableName: "cart",
|
||||||
|
columns: "customer_id",
|
||||||
|
where: "deleted_at IS NULL AND customer_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const SalesChannelIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_cart_sales_channel_id",
|
||||||
|
tableName: "cart",
|
||||||
|
columns: "sales_channel_id",
|
||||||
|
where: "deleted_at IS NULL AND sales_channel_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const CurrencyCodeIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_cart_curency_code",
|
||||||
|
tableName: "cart",
|
||||||
|
columns: "currency_code",
|
||||||
|
where: "deleted_at IS NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const ShippingAddressIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_cart_shipping_address_id",
|
||||||
|
tableName: "cart",
|
||||||
|
columns: "shipping_address_id",
|
||||||
|
where: "deleted_at IS NULL AND shipping_address_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const BillingAddressIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_cart_billing_address_id",
|
||||||
|
tableName: "cart",
|
||||||
|
columns: "billing_address_id",
|
||||||
|
where: "deleted_at IS NULL AND billing_address_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||||
|
tableName: "cart",
|
||||||
|
columns: "deleted_at",
|
||||||
|
where: "deleted_at IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
@Entity({ tableName: "cart" })
|
@Entity({ tableName: "cart" })
|
||||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||||
export default class Cart {
|
export default class Cart {
|
||||||
@@ -34,77 +82,56 @@ export default class Cart {
|
|||||||
@PrimaryKey({ columnType: "text" })
|
@PrimaryKey({ columnType: "text" })
|
||||||
id: string
|
id: string
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@RegionIdIndex()
|
||||||
name: "IDX_cart_region_id",
|
|
||||||
tableName: "cart",
|
|
||||||
columns: "region_id",
|
|
||||||
where: "deleted_at IS NULL AND region_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
region_id: string | null = null
|
region_id: string | null = null
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@CustomerIdIndex()
|
||||||
name: "IDX_cart_customer_id",
|
|
||||||
tableName: "cart",
|
|
||||||
columns: "customer_id",
|
|
||||||
where: "deleted_at IS NULL AND customer_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
customer_id: string | null = null
|
customer_id: string | null = null
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@SalesChannelIdIndex()
|
||||||
name: "IDX_cart_sales_channel_id",
|
@Property({ columnType: "text", nullable: true })
|
||||||
tableName: "cart",
|
|
||||||
columns: "sales_channel_id",
|
|
||||||
where: "deleted_at IS NULL AND sales_channel_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({
|
|
||||||
columnType: "text",
|
|
||||||
nullable: true,
|
|
||||||
index: "IDX_cart_sales_channel_id",
|
|
||||||
})
|
|
||||||
sales_channel_id: string | null = null
|
sales_channel_id: string | null = null
|
||||||
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
email: string | null = null
|
email: string | null = null
|
||||||
|
|
||||||
@Property({ columnType: "text", index: "IDX_cart_curency_code" })
|
@CurrencyCodeIndex()
|
||||||
|
@Property({ columnType: "text" })
|
||||||
currency_code: string
|
currency_code: string
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@ShippingAddressIdIndex()
|
||||||
name: "IDX_cart_shipping_address_id",
|
|
||||||
tableName: "cart",
|
|
||||||
columns: "shipping_address_id",
|
|
||||||
where: "deleted_at IS NULL AND shipping_address_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
|
||||||
shipping_address_id?: string | null
|
|
||||||
|
|
||||||
@ManyToOne({
|
@ManyToOne({
|
||||||
entity: () => Address,
|
entity: () => Address,
|
||||||
|
columnType: "text",
|
||||||
fieldName: "shipping_address_id",
|
fieldName: "shipping_address_id",
|
||||||
|
mapToPk: true,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
cascade: [Cascade.PERSIST],
|
|
||||||
})
|
})
|
||||||
shipping_address?: Address | null
|
shipping_address_id: string | null
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@ManyToOne(() => Address, {
|
||||||
name: "IDX_cart_billing_address_id",
|
cascade: [Cascade.PERSIST],
|
||||||
tableName: "cart",
|
nullable: true,
|
||||||
columns: "billing_address_id",
|
})
|
||||||
where: "deleted_at IS NULL AND billing_address_id IS NOT NULL",
|
shipping_address: Address | null
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
|
||||||
billing_address_id?: string | null
|
|
||||||
|
|
||||||
|
@BillingAddressIdIndex()
|
||||||
@ManyToOne({
|
@ManyToOne({
|
||||||
entity: () => Address,
|
entity: () => Address,
|
||||||
|
columnType: "text",
|
||||||
fieldName: "billing_address_id",
|
fieldName: "billing_address_id",
|
||||||
|
mapToPk: true,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
index: "IDX_cart_billing_address_id",
|
|
||||||
cascade: [Cascade.PERSIST],
|
|
||||||
})
|
})
|
||||||
billing_address?: Address | null
|
billing_address_id: string | null
|
||||||
|
|
||||||
|
@ManyToOne(() => Address, {
|
||||||
|
cascade: [Cascade.PERSIST],
|
||||||
|
nullable: true,
|
||||||
|
})
|
||||||
|
billing_address: Address | null
|
||||||
|
|
||||||
@Property({ columnType: "jsonb", nullable: true })
|
@Property({ columnType: "jsonb", nullable: true })
|
||||||
metadata: Record<string, unknown> | null = null
|
metadata: Record<string, unknown> | null = null
|
||||||
@@ -134,11 +161,7 @@ export default class Cart {
|
|||||||
})
|
})
|
||||||
updated_at: Date
|
updated_at: Date
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@DeletedAtIndex()
|
||||||
tableName: "cart",
|
|
||||||
columns: "deleted_at",
|
|
||||||
where: "deleted_at IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "timestamptz", nullable: true })
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
deleted_at: Date | null = null
|
deleted_at: Date | null = null
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {
|
|||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
BeforeCreate,
|
BeforeCreate,
|
||||||
Cascade,
|
|
||||||
Check,
|
Check,
|
||||||
Entity,
|
Entity,
|
||||||
Filter,
|
Filter,
|
||||||
@@ -16,41 +15,49 @@ import {
|
|||||||
import AdjustmentLine from "./adjustment-line"
|
import AdjustmentLine from "./adjustment-line"
|
||||||
import LineItem from "./line-item"
|
import LineItem from "./line-item"
|
||||||
|
|
||||||
|
const LineItemIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_adjustment_item_id",
|
||||||
|
tableName: "cart_line_item_adjustment",
|
||||||
|
columns: "item_id",
|
||||||
|
where: "deleted_at IS NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const PromotionIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_line_item_adjustment_promotion_id",
|
||||||
|
tableName: "cart_line_item_adjustment",
|
||||||
|
columns: "promotion_id",
|
||||||
|
where: "deleted_at IS NULL AND promotion_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||||
|
tableName: "cart_line_item_adjustment",
|
||||||
|
columns: "deleted_at",
|
||||||
|
where: "deleted_at IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
@Entity({ tableName: "cart_line_item_adjustment" })
|
@Entity({ tableName: "cart_line_item_adjustment" })
|
||||||
@Check<LineItemAdjustment>({
|
@Check<LineItemAdjustment>({
|
||||||
expression: (columns) => `${columns.amount} >= 0`,
|
expression: (columns) => `${columns.amount} >= 0`,
|
||||||
})
|
})
|
||||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||||
export default class LineItemAdjustment extends AdjustmentLine {
|
export default class LineItemAdjustment extends AdjustmentLine {
|
||||||
@ManyToOne({
|
@ManyToOne({ entity: () => LineItem, persist: false })
|
||||||
entity: () => LineItem,
|
|
||||||
cascade: [Cascade.REMOVE, Cascade.PERSIST],
|
|
||||||
})
|
|
||||||
item: LineItem
|
item: LineItem
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@LineItemIdIndex()
|
||||||
name: "IDX_adjustment_item_id",
|
@ManyToOne({
|
||||||
tableName: "cart_line_item_adjustment",
|
entity: () => LineItem,
|
||||||
columns: "item_id",
|
columnType: "text",
|
||||||
where: "deleted_at IS NULL",
|
fieldName: "item_id",
|
||||||
}).MikroORMIndex()
|
mapToPk: true,
|
||||||
@Property({ columnType: "text" })
|
})
|
||||||
item_id: string
|
item_id: string
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@PromotionIdIndex()
|
||||||
name: "IDX_line_item_adjustment_promotion_id",
|
|
||||||
tableName: "cart_line_item_adjustment",
|
|
||||||
columns: "promotion_id",
|
|
||||||
where: "deleted_at IS NULL and promotion_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
promotion_id: string | null = null
|
promotion_id: string | null = null
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@DeletedAtIndex()
|
||||||
tableName: "cart_line_item_adjustment",
|
|
||||||
columns: "deleted_at",
|
|
||||||
where: "deleted_at IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "timestamptz", nullable: true })
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
deleted_at: Date | null = null
|
deleted_at: Date | null = null
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {
|
|||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
BeforeCreate,
|
BeforeCreate,
|
||||||
Cascade,
|
|
||||||
Entity,
|
Entity,
|
||||||
Filter,
|
Filter,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
@@ -15,38 +14,46 @@ import {
|
|||||||
import LineItem from "./line-item"
|
import LineItem from "./line-item"
|
||||||
import TaxLine from "./tax-line"
|
import TaxLine from "./tax-line"
|
||||||
|
|
||||||
|
const LineItemIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_tax_line_item_id",
|
||||||
|
tableName: "cart_line_item_tax_line",
|
||||||
|
columns: "item_id",
|
||||||
|
where: "deleted_at IS NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const TaxRateIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_line_item_tax_line_tax_rate_id",
|
||||||
|
tableName: "cart_line_item_tax_line",
|
||||||
|
columns: "tax_rate_id",
|
||||||
|
where: "deleted_at IS NULL AND tax_rate_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||||
|
tableName: "cart_line_item_tax_line",
|
||||||
|
columns: "deleted_at",
|
||||||
|
where: "deleted_at IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
@Entity({ tableName: "cart_line_item_tax_line" })
|
@Entity({ tableName: "cart_line_item_tax_line" })
|
||||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||||
export default class LineItemTaxLine extends TaxLine {
|
export default class LineItemTaxLine extends TaxLine {
|
||||||
@ManyToOne({
|
@ManyToOne({ entity: () => LineItem, persist: false })
|
||||||
entity: () => LineItem,
|
|
||||||
cascade: [Cascade.REMOVE, Cascade.PERSIST, "soft-remove"] as any,
|
|
||||||
})
|
|
||||||
item: LineItem
|
item: LineItem
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@LineItemIdIndex()
|
||||||
name: "IDX_tax_line_item_id",
|
@ManyToOne({
|
||||||
tableName: "cart_line_item_tax_line",
|
entity: () => LineItem,
|
||||||
columns: "item_id",
|
columnType: "text",
|
||||||
where: "deleted_at IS NULL",
|
fieldName: "item_id",
|
||||||
}).MikroORMIndex()
|
mapToPk: true,
|
||||||
@Property({ columnType: "text" })
|
})
|
||||||
item_id: string
|
item_id: string
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@TaxRateIdIndex()
|
||||||
name: "IDX_line_item_tax_line_tax_rate_id",
|
|
||||||
tableName: "cart_line_item_tax_line",
|
|
||||||
columns: "tax_rate_id",
|
|
||||||
where: "deleted_at IS NULL AND tax_rate_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
tax_rate_id: string | null = null
|
tax_rate_id: string | null = null
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@DeletedAtIndex()
|
||||||
tableName: "cart_line_item_tax_line",
|
|
||||||
columns: "deleted_at",
|
|
||||||
where: "deleted_at IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "timestamptz", nullable: true })
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
deleted_at: Date | null = null
|
deleted_at: Date | null = null
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
OneToMany,
|
OneToMany,
|
||||||
OptionalProps,
|
OptionalProps,
|
||||||
PrimaryKey,
|
PrimaryKey,
|
||||||
Property,
|
Property
|
||||||
} from "@mikro-orm/core"
|
} from "@mikro-orm/core"
|
||||||
import Cart from "./cart"
|
import Cart from "./cart"
|
||||||
import LineItemAdjustment from "./line-item-adjustment"
|
import LineItemAdjustment from "./line-item-adjustment"
|
||||||
@@ -31,6 +31,33 @@ type OptionalLineItemProps =
|
|||||||
| "cart"
|
| "cart"
|
||||||
| DAL.SoftDeletableEntityDateColumns
|
| DAL.SoftDeletableEntityDateColumns
|
||||||
|
|
||||||
|
const CartIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_line_item_cart_id",
|
||||||
|
tableName: "cart_line_item",
|
||||||
|
columns: "cart_id",
|
||||||
|
where: "deleted_at IS NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const VariantIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_line_item_variant_id",
|
||||||
|
tableName: "cart_line_item",
|
||||||
|
columns: "variant_id",
|
||||||
|
where: "deleted_at IS NULL AND variant_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const ProductIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_line_item_product_id",
|
||||||
|
tableName: "cart_line_item",
|
||||||
|
columns: "product_id",
|
||||||
|
where: "deleted_at IS NULL AND product_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||||
|
tableName: "cart_line_item",
|
||||||
|
columns: "deleted_at",
|
||||||
|
where: "deleted_at IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
@Entity({ tableName: "cart_line_item" })
|
@Entity({ tableName: "cart_line_item" })
|
||||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||||
export default class LineItem {
|
export default class LineItem {
|
||||||
@@ -39,19 +66,16 @@ export default class LineItem {
|
|||||||
@PrimaryKey({ columnType: "text" })
|
@PrimaryKey({ columnType: "text" })
|
||||||
id: string
|
id: string
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@CartIdIndex()
|
||||||
name: "IDX_line_item_cart_id",
|
|
||||||
tableName: "cart_line_item",
|
|
||||||
columns: "cart_id",
|
|
||||||
where: "deleted_at IS NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text" })
|
|
||||||
cart_id: string
|
|
||||||
|
|
||||||
@ManyToOne({
|
@ManyToOne({
|
||||||
entity: () => Cart,
|
entity: () => Cart,
|
||||||
cascade: [Cascade.REMOVE, Cascade.PERSIST, "soft-remove"] as any,
|
columnType: "text",
|
||||||
|
fieldName: "cart_id",
|
||||||
|
mapToPk: true,
|
||||||
})
|
})
|
||||||
|
cart_id: string
|
||||||
|
|
||||||
|
@ManyToOne({ entity: () => Cart, persist: false })
|
||||||
cart: Cart
|
cart: Cart
|
||||||
|
|
||||||
@Property({ columnType: "text" })
|
@Property({ columnType: "text" })
|
||||||
@@ -66,21 +90,11 @@ export default class LineItem {
|
|||||||
@Property({ columnType: "integer" })
|
@Property({ columnType: "integer" })
|
||||||
quantity: number
|
quantity: number
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@VariantIdIndex()
|
||||||
name: "IDX_line_item_variant_id",
|
|
||||||
tableName: "cart_line_item",
|
|
||||||
columns: "variant_id",
|
|
||||||
where: "deleted_at IS NULL AND variant_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
variant_id: string | null = null
|
variant_id: string | null = null
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@ProductIdIndex()
|
||||||
name: "IDX_line_item_product_id",
|
|
||||||
tableName: "cart_line_item",
|
|
||||||
columns: "product_id",
|
|
||||||
where: "deleted_at IS NULL AND product_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
product_id: string | null = null
|
product_id: string | null = null
|
||||||
|
|
||||||
@@ -145,6 +159,9 @@ export default class LineItem {
|
|||||||
})
|
})
|
||||||
adjustments = new Collection<LineItemAdjustment>(this)
|
adjustments = new Collection<LineItemAdjustment>(this)
|
||||||
|
|
||||||
|
@Property({ columnType: "jsonb", nullable: true })
|
||||||
|
metadata: Record<string, unknown> | null = null
|
||||||
|
|
||||||
@Property({
|
@Property({
|
||||||
onCreate: () => new Date(),
|
onCreate: () => new Date(),
|
||||||
columnType: "timestamptz",
|
columnType: "timestamptz",
|
||||||
@@ -160,11 +177,7 @@ export default class LineItem {
|
|||||||
})
|
})
|
||||||
updated_at: Date
|
updated_at: Date
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@DeletedAtIndex()
|
||||||
tableName: "cart_line_item",
|
|
||||||
columns: "deleted_at",
|
|
||||||
where: "deleted_at IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "timestamptz", nullable: true })
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
deleted_at: Date | null = null
|
deleted_at: Date | null = null
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {
|
|||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
BeforeCreate,
|
BeforeCreate,
|
||||||
Cascade,
|
|
||||||
Entity,
|
Entity,
|
||||||
Filter,
|
Filter,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
@@ -15,38 +14,46 @@ import {
|
|||||||
import AdjustmentLine from "./adjustment-line"
|
import AdjustmentLine from "./adjustment-line"
|
||||||
import ShippingMethod from "./shipping-method"
|
import ShippingMethod from "./shipping-method"
|
||||||
|
|
||||||
|
const ShippingMethodIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_adjustment_shipping_method_id",
|
||||||
|
tableName: "cart_shipping_method_adjustment",
|
||||||
|
columns: "shipping_method_id",
|
||||||
|
where: "deleted_at IS NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const PromotionIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_shipping_method_adjustment_promotion_id",
|
||||||
|
tableName: "cart_shipping_method_adjustment",
|
||||||
|
columns: "promotion_id",
|
||||||
|
where: "deleted_at IS NULL AND promotion_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||||
|
tableName: "cart_shipping_method_adjustment",
|
||||||
|
columns: "deleted_at",
|
||||||
|
where: "deleted_at IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
@Entity({ tableName: "cart_shipping_method_adjustment" })
|
@Entity({ tableName: "cart_shipping_method_adjustment" })
|
||||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||||
export default class ShippingMethodAdjustment extends AdjustmentLine {
|
export default class ShippingMethodAdjustment extends AdjustmentLine {
|
||||||
@ManyToOne({
|
@ManyToOne({ entity: () => ShippingMethod, persist: false })
|
||||||
entity: () => ShippingMethod,
|
|
||||||
cascade: [Cascade.REMOVE, Cascade.PERSIST],
|
|
||||||
})
|
|
||||||
shipping_method: ShippingMethod
|
shipping_method: ShippingMethod
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@ShippingMethodIdIndex()
|
||||||
name: "IDX_adjustment_shipping_method_id",
|
@ManyToOne({
|
||||||
tableName: "cart_shipping_method_adjustment",
|
entity: () => ShippingMethod,
|
||||||
columns: "shipping_method_id",
|
columnType: "text",
|
||||||
where: "deleted_at IS NULL",
|
fieldName: "shipping_method_id",
|
||||||
}).MikroORMIndex()
|
mapToPk: true,
|
||||||
@Property({ columnType: "text" })
|
})
|
||||||
shipping_method_id: string
|
shipping_method_id: string
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@PromotionIdIndex()
|
||||||
name: "IDX_shipping_method_adjustment_promotion_id",
|
|
||||||
tableName: "cart_shipping_method_adjustment",
|
|
||||||
columns: "promotion_id",
|
|
||||||
where: "deleted_at IS NULL and promotion_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
promotion_id: string | null = null
|
promotion_id: string | null = null
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@DeletedAtIndex()
|
||||||
tableName: "cart_shipping_method_adjustment",
|
|
||||||
columns: "deleted_at",
|
|
||||||
where: "deleted_at IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "timestamptz", nullable: true })
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
deleted_at: Date | null = null
|
deleted_at: Date | null = null
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {
|
|||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
BeforeCreate,
|
BeforeCreate,
|
||||||
Cascade,
|
|
||||||
Entity,
|
Entity,
|
||||||
Filter,
|
Filter,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
@@ -15,38 +14,46 @@ import {
|
|||||||
import ShippingMethod from "./shipping-method"
|
import ShippingMethod from "./shipping-method"
|
||||||
import TaxLine from "./tax-line"
|
import TaxLine from "./tax-line"
|
||||||
|
|
||||||
|
const ShippingMethodIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_tax_line_shipping_method_id",
|
||||||
|
tableName: "cart_shipping_method_tax_line",
|
||||||
|
columns: "shipping_method_id",
|
||||||
|
where: "deleted_at IS NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const TaxRateIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_shipping_method_tax_line_tax_rate_id",
|
||||||
|
tableName: "cart_shipping_method_tax_line",
|
||||||
|
columns: "tax_rate_id",
|
||||||
|
where: "deleted_at IS NULL AND tax_rate_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||||
|
tableName: "cart_shipping_method_tax_line",
|
||||||
|
columns: "deleted_at",
|
||||||
|
where: "deleted_at IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
@Entity({ tableName: "cart_shipping_method_tax_line" })
|
@Entity({ tableName: "cart_shipping_method_tax_line" })
|
||||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||||
export default class ShippingMethodTaxLine extends TaxLine {
|
export default class ShippingMethodTaxLine extends TaxLine {
|
||||||
@ManyToOne({
|
@ManyToOne({ entity: () => ShippingMethod, persist: false })
|
||||||
entity: () => ShippingMethod,
|
|
||||||
cascade: [Cascade.REMOVE, Cascade.PERSIST, "soft-remove"] as any,
|
|
||||||
})
|
|
||||||
shipping_method: ShippingMethod
|
shipping_method: ShippingMethod
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@ShippingMethodIdIndex()
|
||||||
name: "IDX_tax_line_shipping_method_id",
|
@ManyToOne({
|
||||||
tableName: "cart_shipping_method_tax_line",
|
entity: () => ShippingMethod,
|
||||||
columns: "shipping_method_id",
|
columnType: "text",
|
||||||
where: "deleted_at IS NULL",
|
fieldName: "shipping_method_id",
|
||||||
}).MikroORMIndex()
|
mapToPk: true,
|
||||||
@Property({ columnType: "text" })
|
})
|
||||||
shipping_method_id: string
|
shipping_method_id: string
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@TaxRateIdIndex()
|
||||||
name: "IDX_shipping_method_tax_line_tax_rate_id",
|
|
||||||
tableName: "cart_shipping_method_tax_line",
|
|
||||||
columns: "tax_rate_id",
|
|
||||||
where: "deleted_at IS NULL AND tax_rate_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
tax_rate_id: string | null = null
|
tax_rate_id: string | null = null
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@DeletedAtIndex()
|
||||||
tableName: "cart_shipping_method_tax_line",
|
|
||||||
columns: "deleted_at",
|
|
||||||
where: "deleted_at IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "timestamptz", nullable: true })
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
deleted_at: Date | null = null
|
deleted_at: Date | null = null
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,26 @@ type OptionalShippingMethodProps =
|
|||||||
| "is_tax_inclusive"
|
| "is_tax_inclusive"
|
||||||
| DAL.SoftDeletableEntityDateColumns
|
| DAL.SoftDeletableEntityDateColumns
|
||||||
|
|
||||||
|
const CartIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_shipping_method_cart_id",
|
||||||
|
tableName: "cart_shipping_method",
|
||||||
|
columns: "cart_id",
|
||||||
|
where: "deleted_at IS NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const ShippingOptionIdIndex = createPsqlIndexStatementHelper({
|
||||||
|
name: "IDX_shipping_method_option_id",
|
||||||
|
tableName: "cart_shipping_method",
|
||||||
|
columns: "shipping_option_id",
|
||||||
|
where: "deleted_at IS NULL AND shipping_option_id IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
|
const DeletedAtIndex = createPsqlIndexStatementHelper({
|
||||||
|
tableName: "cart_shipping_method",
|
||||||
|
columns: "deleted_at",
|
||||||
|
where: "deleted_at IS NOT NULL",
|
||||||
|
}).MikroORMIndex
|
||||||
|
|
||||||
@Entity({ tableName: "cart_shipping_method" })
|
@Entity({ tableName: "cart_shipping_method" })
|
||||||
@Check<ShippingMethod>({ expression: (columns) => `${columns.amount} >= 0` })
|
@Check<ShippingMethod>({ expression: (columns) => `${columns.amount} >= 0` })
|
||||||
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions)
|
||||||
@@ -38,19 +58,16 @@ export default class ShippingMethod {
|
|||||||
@PrimaryKey({ columnType: "text" })
|
@PrimaryKey({ columnType: "text" })
|
||||||
id: string
|
id: string
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@CartIdIndex()
|
||||||
name: "IDX_shipping_method_cart_id",
|
|
||||||
tableName: "cart_shipping_method",
|
|
||||||
columns: "cart_id",
|
|
||||||
where: "deleted_at IS NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text" })
|
|
||||||
cart_id: string
|
|
||||||
|
|
||||||
@ManyToOne({
|
@ManyToOne({
|
||||||
entity: () => Cart,
|
entity: () => Cart,
|
||||||
cascade: [Cascade.REMOVE, Cascade.PERSIST],
|
columnType: "text",
|
||||||
|
fieldName: "cart_id",
|
||||||
|
mapToPk: true,
|
||||||
})
|
})
|
||||||
|
cart_id: string
|
||||||
|
|
||||||
|
@ManyToOne({ entity: () => Cart, persist: false })
|
||||||
cart: Cart
|
cart: Cart
|
||||||
|
|
||||||
@Property({ columnType: "text" })
|
@Property({ columnType: "text" })
|
||||||
@@ -68,12 +85,7 @@ export default class ShippingMethod {
|
|||||||
@Property({ columnType: "boolean" })
|
@Property({ columnType: "boolean" })
|
||||||
is_tax_inclusive = false
|
is_tax_inclusive = false
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@ShippingOptionIdIndex()
|
||||||
name: "IDX_shipping_method_option_id",
|
|
||||||
tableName: "cart_shipping_method",
|
|
||||||
columns: "shipping_option_id",
|
|
||||||
where: "deleted_at IS NULL AND shipping_option_id IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
shipping_option_id: string | null = null
|
shipping_option_id: string | null = null
|
||||||
|
|
||||||
@@ -116,11 +128,7 @@ export default class ShippingMethod {
|
|||||||
})
|
})
|
||||||
updated_at: Date
|
updated_at: Date
|
||||||
|
|
||||||
@createPsqlIndexStatementHelper({
|
@DeletedAtIndex()
|
||||||
tableName: "cart_shipping_method",
|
|
||||||
columns: "deleted_at",
|
|
||||||
where: "deleted_at IS NOT NULL",
|
|
||||||
}).MikroORMIndex()
|
|
||||||
@Property({ columnType: "timestamptz", nullable: true })
|
@Property({ columnType: "timestamptz", nullable: true })
|
||||||
deleted_at: Date | null = null
|
deleted_at: Date | null = null
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ export default abstract class TaxLine {
|
|||||||
@Property({ columnType: "text", nullable: true })
|
@Property({ columnType: "text", nullable: true })
|
||||||
provider_id?: string | null
|
provider_id?: string | null
|
||||||
|
|
||||||
|
@Property({ columnType: "jsonb", nullable: true })
|
||||||
|
metadata: Record<string, unknown> | null = null
|
||||||
|
|
||||||
@Property({
|
@Property({
|
||||||
onCreate: () => new Date(),
|
onCreate: () => new Date(),
|
||||||
columnType: "timestamptz",
|
columnType: "timestamptz",
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ export default class CartModuleService<
|
|||||||
: [itemIdsOrSelector]
|
: [itemIdsOrSelector]
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.lineItemService_.delete(toDelete, sharedContext)
|
await this.lineItemService_.softDelete(toDelete, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
async createAddresses(
|
async createAddresses(
|
||||||
@@ -636,7 +636,7 @@ export default class CartModuleService<
|
|||||||
? methodIdsOrSelector
|
? methodIdsOrSelector
|
||||||
: [methodIdsOrSelector]
|
: [methodIdsOrSelector]
|
||||||
}
|
}
|
||||||
await this.shippingMethodService_.delete(toDelete, sharedContext)
|
await this.shippingMethodService_.softDelete(toDelete, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
async addLineItemAdjustments(
|
async addLineItemAdjustments(
|
||||||
@@ -736,7 +736,7 @@ export default class CartModuleService<
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (toDelete.length) {
|
if (toDelete.length) {
|
||||||
await this.lineItemAdjustmentService_.delete(
|
await this.lineItemAdjustmentService_.softDelete(
|
||||||
toDelete.map((adj) => adj!.id),
|
toDelete.map((adj) => adj!.id),
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
@@ -791,7 +791,7 @@ export default class CartModuleService<
|
|||||||
: [adjustmentIdsOrSelector]
|
: [adjustmentIdsOrSelector]
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.lineItemAdjustmentService_.delete(ids, sharedContext)
|
await this.lineItemAdjustmentService_.softDelete(ids, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
@@ -833,7 +833,7 @@ export default class CartModuleService<
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (toDelete.length) {
|
if (toDelete.length) {
|
||||||
await this.shippingMethodAdjustmentService_.delete(
|
await this.shippingMethodAdjustmentService_.softDelete(
|
||||||
toDelete.map((adj) => adj!.id),
|
toDelete.map((adj) => adj!.id),
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
@@ -960,7 +960,7 @@ export default class CartModuleService<
|
|||||||
: [adjustmentIdsOrSelector]
|
: [adjustmentIdsOrSelector]
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.shippingMethodAdjustmentService_.delete(ids, sharedContext)
|
await this.shippingMethodAdjustmentService_.softDelete(ids, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
addLineItemTaxLines(
|
addLineItemTaxLines(
|
||||||
@@ -1058,7 +1058,7 @@ export default class CartModuleService<
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (toDelete.length) {
|
if (toDelete.length) {
|
||||||
await this.lineItemTaxLineService_.delete(
|
await this.lineItemTaxLineService_.softDelete(
|
||||||
toDelete.map((taxLine) => taxLine!.id),
|
toDelete.map((taxLine) => taxLine!.id),
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
@@ -1114,7 +1114,7 @@ export default class CartModuleService<
|
|||||||
: [taxLineIdsOrSelector]
|
: [taxLineIdsOrSelector]
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.lineItemTaxLineService_.delete(ids, sharedContext)
|
await this.lineItemTaxLineService_.softDelete(ids, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
addShippingMethodTaxLines(
|
addShippingMethodTaxLines(
|
||||||
@@ -1216,7 +1216,7 @@ export default class CartModuleService<
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (toDelete.length) {
|
if (toDelete.length) {
|
||||||
await this.shippingMethodTaxLineService_.delete(
|
await this.shippingMethodTaxLineService_.softDelete(
|
||||||
toDelete.map((taxLine) => taxLine!.id),
|
toDelete.map((taxLine) => taxLine!.id),
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
@@ -1271,6 +1271,6 @@ export default class CartModuleService<
|
|||||||
: [taxLineIdsOrSelector]
|
: [taxLineIdsOrSelector]
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.shippingMethodTaxLineService_.delete(ids, sharedContext)
|
await this.shippingMethodTaxLineService_.softDelete(ids, sharedContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,3 +2,5 @@ export * from "./add-to-cart"
|
|||||||
export * from "./create-carts"
|
export * from "./create-carts"
|
||||||
export * from "./update-cart"
|
export * from "./update-cart"
|
||||||
export * from "./update-cart-promotions"
|
export * from "./update-cart-promotions"
|
||||||
|
export * from "./update-line-item-in-cart"
|
||||||
|
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import { UpdateLineItemInCartWorkflowInputDTO } from "@medusajs/types"
|
||||||
|
import {
|
||||||
|
WorkflowData,
|
||||||
|
createWorkflow,
|
||||||
|
transform,
|
||||||
|
} from "@medusajs/workflows-sdk"
|
||||||
|
import { getVariantPriceSetsStep } from ".."
|
||||||
|
import { updateLineItemsStep } from "../../line-item/steps"
|
||||||
|
|
||||||
|
// TODO: The UpdateLineItemsWorkflow are missing the following steps:
|
||||||
|
// - Confirm inventory exists (inventory module)
|
||||||
|
// - Validate shipping methods for new items (fulfillment module)
|
||||||
|
// - Refresh line item adjustments (promotion module)
|
||||||
|
// - Update payment sessions (payment module)
|
||||||
|
|
||||||
|
export const updateLineItemInCartWorkflowId = "update-line-item-in-cart"
|
||||||
|
export const updateLineItemInCartWorkflow = createWorkflow(
|
||||||
|
updateLineItemInCartWorkflowId,
|
||||||
|
(input: WorkflowData<UpdateLineItemInCartWorkflowInputDTO>) => {
|
||||||
|
const item = transform({ input }, (data) => data.input.item)
|
||||||
|
|
||||||
|
const pricingContext = transform({ cart: input.cart, item }, (data) => {
|
||||||
|
return {
|
||||||
|
currency_code: data.cart.currency_code,
|
||||||
|
region_id: data.cart.region_id,
|
||||||
|
customer_id: data.cart.customer_id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const variantIds = transform({ input }, (data) => [
|
||||||
|
data.input.item.variant_id!,
|
||||||
|
])
|
||||||
|
|
||||||
|
const priceSets = getVariantPriceSetsStep({
|
||||||
|
variantIds,
|
||||||
|
context: pricingContext,
|
||||||
|
})
|
||||||
|
|
||||||
|
const lineItemUpdate = transform({ input, priceSets, item }, (data) => {
|
||||||
|
const price = data.priceSets[data.item.variant_id!].calculated_amount
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
...data.input.update,
|
||||||
|
unit_price: price,
|
||||||
|
},
|
||||||
|
selector: {
|
||||||
|
id: data.input.item.id,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const result = updateLineItemsStep({
|
||||||
|
data: lineItemUpdate.data,
|
||||||
|
selector: lineItemUpdate.selector,
|
||||||
|
})
|
||||||
|
|
||||||
|
const updatedItem = transform({ result }, (data) => data.result?.[0])
|
||||||
|
|
||||||
|
return updatedItem
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
export * from "./cart"
|
export * from "./cart"
|
||||||
export * from "./inventory"
|
export * from "./inventory"
|
||||||
|
export * from "./line-item"
|
||||||
export * from "./price-list"
|
export * from "./price-list"
|
||||||
export * from "./product"
|
export * from "./product"
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from "./steps"
|
||||||
|
export * from "./workflows"
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import { ICartModuleService } from "@medusajs/types"
|
||||||
|
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
export const deleteLineItemsStepId = "delete-line-items"
|
||||||
|
export const deleteLineItemsStep = createStep(
|
||||||
|
deleteLineItemsStepId,
|
||||||
|
async (ids: string[], { container }) => {
|
||||||
|
const service = container.resolve<ICartModuleService>(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
await service.removeLineItems(ids)
|
||||||
|
|
||||||
|
return new StepResponse(void 0, ids)
|
||||||
|
},
|
||||||
|
async (ids, { container }) => {
|
||||||
|
if (!ids?.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const service = container.resolve<ICartModuleService>(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
await service.restoreLineItems(ids)
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export * from "./delete-line-items"
|
||||||
|
export * from "./list-line-items"
|
||||||
|
export * from "./update-line-items"
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import {
|
||||||
|
CartLineItemDTO,
|
||||||
|
FilterableLineItemProps,
|
||||||
|
FindConfig,
|
||||||
|
ICartModuleService,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
interface StepInput {
|
||||||
|
filters: FilterableLineItemProps
|
||||||
|
config?: FindConfig<CartLineItemDTO>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const listLineItemsStepId = "list-line-items"
|
||||||
|
export const listLineItemsStep = createStep(
|
||||||
|
listLineItemsStepId,
|
||||||
|
async (data: StepInput, { container }) => {
|
||||||
|
const service = container.resolve<ICartModuleService>(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
const items = await service.listLineItems(data.filters, data.config)
|
||||||
|
|
||||||
|
return new StepResponse(items)
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import {
|
||||||
|
ICartModuleService,
|
||||||
|
UpdateLineItemWithSelectorDTO,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import {
|
||||||
|
getSelectsAndRelationsFromObjectArray,
|
||||||
|
promiseAll,
|
||||||
|
removeUndefined,
|
||||||
|
} from "@medusajs/utils"
|
||||||
|
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
export const updateLineItemsStepId = "update-line-items"
|
||||||
|
export const updateLineItemsStep = createStep(
|
||||||
|
updateLineItemsStepId,
|
||||||
|
async (input: UpdateLineItemWithSelectorDTO, { container }) => {
|
||||||
|
const service = container.resolve<ICartModuleService>(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
const { selects, relations } = getSelectsAndRelationsFromObjectArray([
|
||||||
|
input.data,
|
||||||
|
])
|
||||||
|
|
||||||
|
const itemsBefore = await service.listLineItems(input.selector, {
|
||||||
|
select: selects,
|
||||||
|
relations,
|
||||||
|
})
|
||||||
|
|
||||||
|
const items = await service.updateLineItems(input.selector, input.data)
|
||||||
|
|
||||||
|
return new StepResponse(items, itemsBefore)
|
||||||
|
},
|
||||||
|
async (itemsBefore, { container }) => {
|
||||||
|
if (!itemsBefore) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const service = container.resolve<ICartModuleService>(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
await promiseAll(
|
||||||
|
itemsBefore.map(async (i) =>
|
||||||
|
service.updateLineItems(
|
||||||
|
i.id,
|
||||||
|
removeUndefined({
|
||||||
|
quantity: i.quantity,
|
||||||
|
title: i.title,
|
||||||
|
metadata: i.metadata,
|
||||||
|
unit_price: i.unit_price,
|
||||||
|
tax_lines: i.tax_lines,
|
||||||
|
adjustments: i.adjustments,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||||
|
import { deleteLineItemsStep } from "../steps/delete-line-items"
|
||||||
|
|
||||||
|
type WorkflowInput = { ids: string[] }
|
||||||
|
|
||||||
|
// TODO: The DeleteLineItemsWorkflow are missing the following steps:
|
||||||
|
// - Refresh/delete shipping methods (fulfillment module)
|
||||||
|
// - Refresh line item adjustments (promotion module)
|
||||||
|
// - Update payment sessions (payment module)
|
||||||
|
|
||||||
|
export const deleteLineItemsWorkflowId = "delete-line-items"
|
||||||
|
export const deleteLineItemsWorkflow = createWorkflow(
|
||||||
|
deleteLineItemsWorkflowId,
|
||||||
|
(input: WorkflowData<WorkflowInput>) => {
|
||||||
|
return deleteLineItemsStep(input.ids)
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./delete-line-items"
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import {
|
||||||
|
deleteLineItemsWorkflow,
|
||||||
|
updateLineItemInCartWorkflow,
|
||||||
|
} from "@medusajs/core-flows"
|
||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import { ICartModuleService } from "@medusajs/types"
|
||||||
|
import { MedusaError, remoteQueryObjectFromString } from "@medusajs/utils"
|
||||||
|
import { MedusaRequest, MedusaResponse } from "../../../../../../types/routing"
|
||||||
|
import { defaultStoreCartFields } from "../../../query-config"
|
||||||
|
import { StorePostCartsCartLineItemsItemReq } from "./validators"
|
||||||
|
|
||||||
|
export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
|
||||||
|
const cartModuleService = req.scope.resolve<ICartModuleService>(
|
||||||
|
ModuleRegistrationName.CART
|
||||||
|
)
|
||||||
|
|
||||||
|
const cart = await cartModuleService.retrieve(req.params.id, {
|
||||||
|
select: ["id", "region_id", "currency_code"],
|
||||||
|
relations: ["region", "items", "items.variant_id"],
|
||||||
|
})
|
||||||
|
|
||||||
|
const item = cart.items?.find((i) => i.id === req.params.line_id)
|
||||||
|
|
||||||
|
if (!item) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_FOUND,
|
||||||
|
`Line item with id: ${req.params.line_id} was not found`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = {
|
||||||
|
cart,
|
||||||
|
item,
|
||||||
|
update: req.validatedBody as StorePostCartsCartLineItemsItemReq,
|
||||||
|
}
|
||||||
|
|
||||||
|
const { errors } = await updateLineItemInCartWorkflow(req.scope).run({
|
||||||
|
input,
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (Array.isArray(errors) && errors[0]) {
|
||||||
|
throw errors[0].error
|
||||||
|
}
|
||||||
|
|
||||||
|
const remoteQuery = req.scope.resolve("remoteQuery")
|
||||||
|
|
||||||
|
const query = remoteQueryObjectFromString({
|
||||||
|
entryPoint: "cart",
|
||||||
|
fields: defaultStoreCartFields,
|
||||||
|
})
|
||||||
|
|
||||||
|
const [updatedCart] = await remoteQuery(query, {
|
||||||
|
cart: { id: req.params.id },
|
||||||
|
})
|
||||||
|
|
||||||
|
res.status(200).json({ cart: updatedCart })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DELETE = async (req: MedusaRequest, res: MedusaResponse) => {
|
||||||
|
const id = req.params.line_id
|
||||||
|
|
||||||
|
const { errors } = await deleteLineItemsWorkflow(req.scope).run({
|
||||||
|
input: { ids: [id] },
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (Array.isArray(errors) && errors[0]) {
|
||||||
|
throw errors[0].error
|
||||||
|
}
|
||||||
|
|
||||||
|
const remoteQuery = req.scope.resolve("remoteQuery")
|
||||||
|
|
||||||
|
const query = remoteQueryObjectFromString({
|
||||||
|
entryPoint: "cart",
|
||||||
|
fields: defaultStoreCartFields,
|
||||||
|
})
|
||||||
|
|
||||||
|
const [cart] = await remoteQuery(query, {
|
||||||
|
cart: { id: req.params.id },
|
||||||
|
})
|
||||||
|
|
||||||
|
res.status(200).json({ cart })
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { IsInt, IsOptional } from "class-validator"
|
||||||
|
|
||||||
|
export class StorePostCartsCartLineItemsItemReq {
|
||||||
|
@IsInt()
|
||||||
|
quantity: number
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
metadata?: Record<string, unknown> | undefined
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { transformBody, transformQuery } from "../../../api/middlewares"
|
import { transformBody, transformQuery } from "../../../api/middlewares"
|
||||||
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
|
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
|
||||||
import { authenticate } from "../../../utils/authenticate-middleware"
|
import { authenticate } from "../../../utils/authenticate-middleware"
|
||||||
|
import { StorePostCartsCartLineItemsItemReq } from "./[id]/line-items/[line_id]/validators"
|
||||||
import { StorePostCartsCartLineItemsReq } from "./[id]/line-items/validators"
|
import { StorePostCartsCartLineItemsReq } from "./[id]/line-items/validators"
|
||||||
import * as QueryConfig from "./query-config"
|
import * as QueryConfig from "./query-config"
|
||||||
import {
|
import {
|
||||||
@@ -48,6 +49,14 @@ export const storeCartRoutesMiddlewares: MiddlewareRoute[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: ["POST"],
|
method: ["POST"],
|
||||||
|
matcher: "/store/carts/:id/line-items/:line_id",
|
||||||
|
middlewares: [transformBody(StorePostCartsCartLineItemsItemReq)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: ["DELETE"],
|
||||||
|
matcher: "/store/carts/:id/line-items/:line_id",
|
||||||
|
},
|
||||||
|
{
|
||||||
matcher: "/store/carts/:id/promotions",
|
matcher: "/store/carts/:id/promotions",
|
||||||
middlewares: [transformBody(StorePostCartsCartPromotionsReq)],
|
middlewares: [transformBody(StorePostCartsCartPromotionsReq)],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -400,6 +400,10 @@ export interface CartLineItemDTO extends CartLineItemTotalsDTO {
|
|||||||
* When the line item was updated.
|
* When the line item was updated.
|
||||||
*/
|
*/
|
||||||
updated_at?: Date
|
updated_at?: Date
|
||||||
|
/**
|
||||||
|
* When the line item was deleted.
|
||||||
|
*/
|
||||||
|
deleted_at?: Date
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CartDTO {
|
export interface CartDTO {
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ export interface UpdateLineItemDTO
|
|||||||
title?: string
|
title?: string
|
||||||
quantity?: number
|
quantity?: number
|
||||||
unit_price?: number
|
unit_price?: number
|
||||||
|
metadata?: Record<string, unknown> | null
|
||||||
|
|
||||||
tax_lines?: UpdateTaxLineDTO[] | CreateTaxLineDTO[]
|
tax_lines?: UpdateTaxLineDTO[] | CreateTaxLineDTO[]
|
||||||
adjustments?: UpdateAdjustmentDTO[] | CreateAdjustmentDTO[]
|
adjustments?: UpdateAdjustmentDTO[] | CreateAdjustmentDTO[]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { CartDTO } from "./common"
|
import { CartDTO, CartLineItemDTO } from "./common"
|
||||||
|
import { UpdateLineItemDTO } from "./mutations"
|
||||||
|
|
||||||
export interface CreateCartCreateLineItemDTO {
|
export interface CreateCartCreateLineItemDTO {
|
||||||
quantity: number
|
quantity: number
|
||||||
@@ -32,6 +33,12 @@ export interface CreateCartCreateLineItemDTO {
|
|||||||
metadata?: Record<string, unknown>
|
metadata?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpdateLineItemInCartWorkflowInputDTO {
|
||||||
|
cart: CartDTO
|
||||||
|
item: CartLineItemDTO
|
||||||
|
update: Partial<UpdateLineItemDTO>
|
||||||
|
}
|
||||||
|
|
||||||
export interface CreateCartAddressDTO {
|
export interface CreateCartAddressDTO {
|
||||||
first_name?: string
|
first_name?: string
|
||||||
last_name?: string
|
last_name?: string
|
||||||
|
|||||||
@@ -2,19 +2,19 @@ import {
|
|||||||
BaseFilterable,
|
BaseFilterable,
|
||||||
Context,
|
Context,
|
||||||
FilterQuery,
|
FilterQuery,
|
||||||
FilterQuery as InternalFilterQuery,
|
|
||||||
FindConfig,
|
FindConfig,
|
||||||
|
FilterQuery as InternalFilterQuery,
|
||||||
ModulesSdkTypes,
|
ModulesSdkTypes,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import { EntitySchema } from "@mikro-orm/core"
|
import { EntitySchema } from "@mikro-orm/core"
|
||||||
import { EntityClass } from "@mikro-orm/core/typings"
|
import { EntityClass } from "@mikro-orm/core/typings"
|
||||||
import {
|
import {
|
||||||
|
MedusaError,
|
||||||
doNotForceTransaction,
|
doNotForceTransaction,
|
||||||
isDefined,
|
isDefined,
|
||||||
isObject,
|
isObject,
|
||||||
isString,
|
isString,
|
||||||
lowerCaseFirst,
|
lowerCaseFirst,
|
||||||
MedusaError,
|
|
||||||
shouldForceTransaction,
|
shouldForceTransaction,
|
||||||
} from "../common"
|
} from "../common"
|
||||||
import { buildQuery } from "./build-query"
|
import { buildQuery } from "./build-query"
|
||||||
|
|||||||
Reference in new issue
Block a user