From 00fd096d25968a9c32ea5c582a52d1a10ddfc729 Mon Sep 17 00:00:00 2001 From: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com> Date: Wed, 27 Apr 2022 15:25:04 +0700 Subject: [PATCH] Feat: Discount migration (#1214) * feat: Add DiscountCondition entity + Join table per relation (#1146) * feat: Convert DiscountService to TypeScript (#1149) * feat: Add DiscountRepository + bulk insert and remove (#1156) * feat: Add `conditions` to payload in `POST /discounts` and `POST /discounts/:id` (#1170) * feat: Add DiscountRuleCondition entity * fix relation * fix join key * Add discount rule condition repo * add join table per relation * Convert DiscountService to TypeScript * feat: Add DiscountConditionRepository * Add migration + remove use of valid_for * revert changes to files, not done yet * init work on create discount endpoint * Add conditions to create discount endpoint * Add conditions to update discount endpoint * Add unique constraint to discount condition * integration tests passing * fix imports of models * fix tests (excluding totals calculations) * Fix commented code * add unique constraint on discount condition * Add generic way of generating retrieve configs * Requested changes + ExactlyOne validator * Remove isLocal flag from error handler * Use postgres error constant * remove commented code * initial * add migration scripts * make getMigrationsFolder generic * add datamodel migration command * add datamodel run to migraitons cli * remove data migration code from migrations * add inner join * add migration script for discount migration * redo all script changes after adding script file * address pr feedback * cherrypick files from develop * remove unused import * suggestions * Update packages/medusa/src/scripts/discount-rule-migration.ts Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> * fix: revert rule id to dr_id Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> Co-authored-by: olivermrbl --- .../src/scripts/discount-rule-migration.ts | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 packages/medusa/src/scripts/discount-rule-migration.ts diff --git a/packages/medusa/src/scripts/discount-rule-migration.ts b/packages/medusa/src/scripts/discount-rule-migration.ts new file mode 100644 index 0000000000..5acbcc16ed --- /dev/null +++ b/packages/medusa/src/scripts/discount-rule-migration.ts @@ -0,0 +1,132 @@ +import dotenv from "dotenv" +import { createConnection } from "typeorm" +import Logger from "../loaders/logger" +import { + DiscountCondition, + DiscountConditionOperator, + DiscountConditionType, +} from "../models/discount-condition" +import { DiscountConditionProduct } from "../models/discount-condition-product" +import { DiscountRule } from "../models/discount-rule" +dotenv.config() + +const typeormConfig = { + type: process.env.TYPEORM_CONNECTION, + url: process.env.TYPEORM_URL, + username: process.env.TYPEORM_USERNAME, + password: process.env.TYPEORM_PASSWORD, + database: process.env.TYPEORM_DATABASE, + migrations: [process.env.TYPEORM_MIGRATIONS as string], + entities: [process.env.TYPEORM_ENTITIES], + logging: true, +} + +const migrate = async function ({ typeormConfig }): Promise { + const connection = await createConnection(typeormConfig) + + const BATCH_SIZE = 1000 + + await connection.transaction(async (manager) => { + const discountRuleCount = await manager + .createQueryBuilder() + .from(DiscountRule, "dr") + .getCount() + + let offset = 0 + while (offset < discountRuleCount) { + const discountRules = await manager + .createQueryBuilder() + .from(DiscountRule, "dr") + .select("dr.id") + .innerJoin( + "discount_rule_products", + "drp", + "dr.id = drp.discount_rule_id" + ) + .distinct(true) + .limit(BATCH_SIZE) + .offset(offset) + .getRawMany() + + await manager + .createQueryBuilder() + .insert() + .into(DiscountCondition) + .values( + discountRules.map((dr) => + Object.assign(new DiscountCondition(), { + type: DiscountConditionType.PRODUCTS, + operator: DiscountConditionOperator.IN, + discount_rule_id: dr.dr_id, + }) + ) + ) + .orIgnore() + .execute() + offset += BATCH_SIZE + } + + const discountRuleProductCount = await manager.query( + "SELECT COUNT(*) FROM discount_rule_products" + ) + + offset = 0 + while (offset < parseInt(discountRuleProductCount[0].count)) { + const getConditionProductsResult = await manager + .createQueryBuilder() + .from(DiscountRule, "dr") + .innerJoin( + "discount_rule_products", + "drp", + "dr.id = drp.discount_rule_id" + ) + .innerJoin("discount_condition", "dc", "dr.id = dc.discount_rule_id") + .select("dc.id as cond_id, drp.product_id") + .limit(BATCH_SIZE) + .offset(offset) + .getRawMany() + + await manager + .createQueryBuilder() + .insert() + .into(DiscountConditionProduct) + .values( + getConditionProductsResult.map((dr) => ({ + condition_id: dr.cond_id, + product_id: dr.product_id, + })) + ) + .orIgnore() + .execute() + + offset += BATCH_SIZE + } + }) + + // Validate results + const noDanglingProductsValidation = await connection.manager + .query(`SELECT drp.discount_rule_id, drp.product_id, dcp.product_id FROM "discount_rule_products" drp + LEFT JOIN discount_condition dc ON dc.discount_rule_id = drp.discount_rule_id + LEFT JOIN discount_condition_product dcp ON dcp.condition_id = dc.id AND dcp.product_id = drp.product_id + WHERE dcp.product_id IS NULL`) + + if ( + noDanglingProductsValidation && + noDanglingProductsValidation?.length === 0 + ) { + Logger.info(`Discount entities have been successfully migrated`) + process.exit() + } else { + Logger.error(`Discount entities could not be migrated`) + process.exit(1) + } +} + +migrate({ typeormConfig }) + .then(() => { + Logger.info("Database migration completed successfully") + process.exit() + }) + .catch((err) => console.log(err)) + +export default migrate