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:
@@ -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() })
|
||||
Reference in New Issue
Block a user