fix: shipping option updates (#426)

* fix to remove req

* tested fix
This commit is contained in:
Kasper Fabricius Kristensen
2021-10-01 08:18:56 +02:00
committed by GitHub
parent cd4afd1576
commit 22f3f2af93
4 changed files with 66 additions and 41 deletions
@@ -0,0 +1,18 @@
import { MigrationInterface, QueryRunner } from "typeorm"
export class deleteDateOnShippingOptionRequirements1632828114899
implements MigrationInterface {
name = "deleteDateOnShippingOptionRequirements1632828114899"
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "shipping_option_requirement" ADD "deleted_at" TIMESTAMP WITH TIME ZONE`
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "shipping_option_requirement" DROP COLUMN "deleted_at"`
)
}
}
@@ -16,7 +16,7 @@ import {
JoinTable, JoinTable,
} from "typeorm" } from "typeorm"
import { ulid } from "ulid" import { ulid } from "ulid"
import { DbAwareColumn } from "../utils/db-aware-column" import { DbAwareColumn, resolveDbType } from "../utils/db-aware-column"
import { ShippingOption } from "./shipping-option" import { ShippingOption } from "./shipping-option"
@@ -44,6 +44,9 @@ export class ShippingOptionRequirement {
@Column({ type: "int" }) @Column({ type: "int" })
amount: number amount: number
@DeleteDateColumn({ type: resolveDbType("timestamptz") })
deleted_at: Date
@BeforeInsert() @BeforeInsert()
private beforeInsert() { private beforeInsert() {
if (this.id) return if (this.id) return
@@ -296,24 +296,19 @@ describe("ShippingOptionService", () => {
}) })
describe("removeRequirement", () => { describe("removeRequirement", () => {
const shippingOptionRepository = MockRepository({ const shippingOptionRequirementRepository = MockRepository({
findOne: q => { softRemove: q => {
switch (q.where.id) { return Promise.resolve()
default:
return Promise.resolve({
requirements: [
{
id: IdMap.getId("requirement_id"),
},
],
})
}
}, },
findOne: i =>
i.where.id === IdMap.getId("requirement_id")
? { id: IdMap.getId("requirement_id") }
: null,
}) })
const optionService = new ShippingOptionService({ const optionService = new ShippingOptionService({
manager: MockManager, manager: MockManager,
shippingOptionRepository, shippingOptionRequirementRepository,
}) })
beforeEach(() => { beforeEach(() => {
@@ -321,22 +316,19 @@ describe("ShippingOptionService", () => {
}) })
it("remove requirement successfully", async () => { it("remove requirement successfully", async () => {
await optionService.removeRequirement( await optionService.removeRequirement(IdMap.getId("requirement_id"))
IdMap.getId("validId"),
IdMap.getId("requirement_id")
)
expect(shippingOptionRepository.save).toBeCalledTimes(1) expect(shippingOptionRequirementRepository.findOne).toBeCalledTimes(1)
expect(shippingOptionRepository.save).toBeCalledWith({ requirements: [] }) expect(shippingOptionRequirementRepository.findOne).toBeCalledWith({
where: { id: IdMap.getId("requirement_id") },
})
expect(shippingOptionRequirementRepository.softRemove).toBeCalledTimes(1)
}) })
it("is idempotent", async () => { it("is idempotent", async () => {
await optionService.removeRequirement(IdMap.getId("validId"), "something") await optionService.removeRequirement(IdMap.getId("validId"), "something")
expect(shippingOptionRepository.save).toBeCalledTimes(1) expect(shippingOptionRequirementRepository.softRemove).toBeCalledTimes(1)
expect(shippingOptionRepository.save).toBeCalledWith({
requirements: [{ id: IdMap.getId("requirement_id") }],
})
}) })
}) })
+29 -17
View File
@@ -450,7 +450,9 @@ class ShippingOptionService extends BaseService {
*/ */
async update(optionId, update) { async update(optionId, update) {
return this.atomicPhase_(async manager => { return this.atomicPhase_(async manager => {
const option = await this.retrieve(optionId) const option = await this.retrieve(optionId, {
relations: ["requirements"],
})
if ("metadata" in update) { if ("metadata" in update) {
option.metadata = await this.setMetadata_(option, update.metadata) option.metadata = await this.setMetadata_(option, update.metadata)
@@ -498,6 +500,20 @@ class ShippingOptionService extends BaseService {
acc.push(validated) acc.push(validated)
} }
if (option.requirements) {
const accReqs = acc.map(a => a.id)
const toRemove = option.requirements.filter(
r => !accReqs.includes(r.id)
)
await Promise.all(
toRemove.map(async req => {
await this.removeRequirement(req.id)
})
)
}
option.requirements = acc
} }
if ("price_type" in update) { if ("price_type" in update) {
@@ -585,28 +601,24 @@ class ShippingOptionService extends BaseService {
/** /**
* Removes a requirement from a shipping option * Removes a requirement from a shipping option
* @param {string} optionId - the shipping option to remove from
* @param {string} requirementId - the id of the requirement to remove * @param {string} requirementId - the id of the requirement to remove
* @return {Promise} the result of update * @return {Promise} the result of update
*/ */
async removeRequirement(optionId, requirementId) { async removeRequirement(requirementId) {
return this.atomicPhase_(async manager => { return this.atomicPhase_(async manager => {
const option = await this.retrieve(optionId, { try {
relations: "requirements", const reqRepo = manager.getCustomRepository(this.requirementRepository_)
}) const requirement = await reqRepo.findOne({
const newReqs = option.requirements.map(r => { where: { id: requirementId },
if (r.id === requirementId) { })
return null
} else {
return r
}
})
option.requirements = newReqs.filter(Boolean) const result = await reqRepo.softRemove(requirement)
const optionRepo = manager.getCustomRepository(this.optionRepository_) return result
const result = await optionRepo.save(option) } catch (error) {
return result // Delete is idempotent, but we return a promise to allow then-chaining
return Promise.resolve()
}
}) })
} }