feat(medusa): integrate pricing module to core (#5304)

* add pricing integraiton feature flag

* init

* first endpoint

* cleanup

* remove console.logs

* refactor to util and implement across endpoints

* add changeset

* rename variables

* remove mistype

* feat(medusa): move price module integration to pricing service (#5322)

* initial changes

* chore: make product service always internal for pricing module

* add notes

---------

Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>

* nit

* cleanup

* update to object querying

* update cart integration test

* remove uppercase currency_code

* nit

* Feat/admin product pricing module reads (#5354)

* initial changes to list prices for admin

* working price module implementation of list prices

* nit

* variant pricing

* redo integration test changes

* cleanup

* cleanup

* fix unit tests

* [wip] Core <> Pricing - price updates  (#5364)

* chore: update medusa-app

* wip

* get links and modules working with migration

* wip

* chore: make test pass

* Feat/rule type utils (#5371)

* initial rule type utils

* update migration script

* chore: cleanup

* ensure prices are always decorated

* chore: use seed instead

* chore: fix oas conflict

* region id add to admin price read!

---------

Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com>
Co-authored-by: Philip Korsholm <philip.korsholm@hotmail.com>

* pr feedback

* create remoteQueryFunction type

* fix merge

* fix loaders issue

* Feat(medusa, types, pricing): pricing module migration script (#5409)

* add migration script for money amounts in pricing module

* add changeset

* rename file

* cleanup imports

* update changeset

* add check for pricing module and ff

* feat(medusa,workflows,types): update prices on product and variant update (#5412)

* wip

* chore: update product prices through workflow

* chore: cleanup

* chore: update product handler updates prices for variants

* chore: handle reverts

* chore: address pr comments

* chore: scope workflow handlers to flag handlers

* chore: update return

* chore: update db url

* chore: remove migration

* chore: increase jest timeout

* Feat(medusa): update migration and initDb to run link-migrations (#5437)

* initial

* loader update

* more progress on loaders

* update integration tests and remote-query loader

* remove helper

* migrate isolated modules

* fix test

* fix integration test

* update with pr feedback

* unregister medusa-app

* re-register medusaApp

* fix featureflag

* set timeout

* set timeout

* conditionally run link-module migrations

* pr feedback 1

* add driver options for db

* throw if link is not defined in migration script

* pass config module directly

* include container in migrate command

* chore: increase timeout

* rm redis from api integration tests to test

* chore: temporarily skip tests

* chore: undo skips + add timeout for workflow tests

* chore: increase timeout for order edits

* re-add redis

* include final resolution

* add sharedcontainer to medusaapp loader

* chore: move migration under run command

* try removing redis_url from api tests

* chore: cleanup server on process exit

* chore: clear container on exit

* chore: adjustments

* chore: remove consoles

* chore: close express app on finish

* chore: destroy pg connection on shutdown

* chore: skip

* chore: unskip test

* chore: cleanup container pg connection

* chore: skip

---------

Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>
This commit is contained in:
Philip Korsholm
2023-10-30 14:42:17 +01:00
committed by GitHub
parent b69f182571
commit 148f537b47
84 changed files with 2702 additions and 284 deletions
@@ -0,0 +1,44 @@
import { AwilixContainer } from "awilix"
import { IPricingModuleService } from "@medusajs/types"
import dotenv from "dotenv"
import express from "express"
import loaders from "../loaders"
dotenv.config()
export const createDefaultRuleTypes = async (container: AwilixContainer) => {
const pricingModuleService: IPricingModuleService = container.resolve(
"pricingModuleService"
)
const existing = await pricingModuleService.listRuleTypes(
{ rule_attribute: ["region_id"] },
{ take: 1 }
)
if (existing.length) {
return
}
await pricingModuleService.createRuleTypes([
{ name: "region_id", rule_attribute: "region_id" },
])
}
const migrate = async function ({ directory }) {
const app = express()
const { container } = await loaders({
directory,
expressApp: app,
isTest: false,
})
return await createDefaultRuleTypes(container)
}
migrate({ directory: process.cwd() })
.then(() => {
console.log("Created default rule types")
})
.catch(() => {
console.log("Failed to create rule types")
})
@@ -0,0 +1,142 @@
import { FlagRouter, MedusaError } from "@medusajs/utils"
import { IPricingModuleService, MedusaContainer } from "@medusajs/types"
import { AwilixContainer } from "awilix"
import { EntityManager } from "typeorm"
import IsolatePricingDomainFeatureFlag from "../loaders/feature-flags/isolate-pricing-domain"
import { Modules } from "@medusajs/modules-sdk"
import { ProductVariant } from "../models"
import { ProductVariantService } from "../services"
import { createDefaultRuleTypes } from "./create-default-rule-types"
import dotenv from "dotenv"
import express from "express"
import loadMedusaApp from "../loaders/medusa-app"
import loaders from "../loaders"
dotenv.config()
const BATCH_SIZE = 100
const migrateProductVariant = async (
variant: ProductVariant,
{
container,
}: { container: MedusaContainer; transactionManager: EntityManager }
) => {
const pricingService: IPricingModuleService = container.resolve(
"pricingModuleService"
)
const configModule = await container.resolve("configModule")
const { link } = await loadMedusaApp(
{ configModule, container },
{ registerInContainer: false }
)
if (!link) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Can't migrate money_amounts: Pricing module is not configured correctly"
)
}
const priceSet = await pricingService.create({
rules: [{ rule_attribute: "region_id" }],
prices: variant.prices.map((price) => ({
rules: {
region_id: price.region_id,
},
currency_code: price.currency_code,
min_quantity: price.min_quantity,
max_quantity: price.max_quantity,
amount: price.amount,
})),
})
await link.create({
productService: {
variant_id: variant.id,
},
pricingService: {
price_set_id: priceSet.id,
},
})
}
const processBatch = async (
variants: ProductVariant[],
container: MedusaContainer
) => {
const manager = container.resolve("manager")
return await manager.transaction(async (transactionManager) => {
await Promise.all(
variants.map(async (variant) => {
await migrateProductVariant(variant, {
container,
transactionManager,
})
})
)
})
}
const migrate = async function ({ directory }) {
const app = express()
const { container } = await loaders({
directory,
expressApp: app,
isTest: false,
})
const variantService: ProductVariantService = await container.resolve(
"productVariantService"
)
const featureFlagRouter: FlagRouter = await container.resolve(
"featureFlagRouter"
)
if (
!featureFlagRouter.isFeatureEnabled(IsolatePricingDomainFeatureFlag.key) &&
!featureFlagRouter.isFeatureEnabled(Modules.PRICING)
) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Pricing module not enabled"
)
}
await createDefaultRuleTypes(container)
const [variants, totalCount] = await variantService.listAndCount(
{},
{ take: BATCH_SIZE, order: { id: "ASC" }, relations: ["prices"] }
)
await processBatch(variants, container)
let processedCount = variants.length
console.log(`Processed ${processedCount} of ${totalCount}`)
while (processedCount < totalCount) {
const nextBatch = await variantService.list(
{},
{
skip: processedCount,
take: BATCH_SIZE,
order: { id: "ASC" },
relations: ["prices"],
}
)
await processBatch(nextBatch, container)
processedCount += nextBatch.length
console.log(`Processed ${processedCount} of ${totalCount}`)
}
console.log("Done")
process.exit(0)
}
migrate({ directory: process.cwd() })