Updated Offer to only change code once

no-issue

This simplifies the handling of updating redirects for a code, and
doesn't affect our application layer because we never have the need to
change a code twice.

In future this should be replaced with events at the domain level - so
that we do not have to track changed properties and instead a redirect
service can listen to events, which would be dispatched on a successful
save by the repository.
This commit is contained in:
Fabien O'Carroll 2021-10-08 13:02:22 +02:00
parent 1f703920c9
commit 1312943f5b
4 changed files with 14 additions and 12 deletions

View File

@ -20,10 +20,8 @@ class OffersModule {
*/ */
async init() { async init() {
DomainEvents.subscribe(OfferCodeChangeEvent, (event) => { DomainEvents.subscribe(OfferCodeChangeEvent, (event) => {
if (event.data.previousCodes) { if (event.data.previousCode) {
for (const previousCode of event.data.previousCodes) { this.redirectManager.removeRedirect(`/${event.data.previousCode.value}`);
this.redirectManager.removeRedirect(`/${previousCode.value}`);
}
} }
this.redirectManager.addRedirect( this.redirectManager.addRedirect(
`/${event.data.currentCode.value}`, `/${event.data.currentCode.value}`,

View File

@ -131,7 +131,7 @@ class OfferRepository {
if (offer.codeChanged || offer.isNew) { if (offer.codeChanged || offer.isNew) {
const event = OfferCodeChangeEvent.create({ const event = OfferCodeChangeEvent.create({
offerId: offer.id, offerId: offer.id,
previousCodes: offer.isNew ? null : offer.oldCodes, previousCode: offer.oldCode,
currentCode: offer.code currentCode: offer.code
}); });
DomainEvents.dispatch(event); DomainEvents.dispatch(event);

View File

@ -3,7 +3,7 @@
/** /**
* @typedef {object} OfferCodeChangeEventData * @typedef {object} OfferCodeChangeEventData
* @prop {string} offerId * @prop {string} offerId
* @prop {OfferCode[]} previousCodes * @prop {OfferCode} previousCode
* @prop {OfferCode} currentCode * @prop {OfferCode} currentCode
*/ */

View File

@ -117,12 +117,12 @@ class Offer {
return this.props.duration; return this.props.duration;
} }
get oldCodes() { get oldCode() {
return this.changed.code; return this.changed.code;
} }
get codeChanged() { get codeChanged() {
return this.changed.code.length > 0; return this.changed.code !== null;
} }
get displayTitle() { get displayTitle() {
@ -174,12 +174,17 @@ class Offer {
if (code.equals(this.props.code)) { if (code.equals(this.props.code)) {
return; return;
} }
if (this.changed.code) {
throw new errors.InvalidOfferCode({
message: 'Offer `code` cannot be updated more than once.'
});
}
if (!await uniqueChecker.isUniqueCode(code)) { if (!await uniqueChecker.isUniqueCode(code)) {
throw new errors.InvalidOfferCode({ throw new errors.InvalidOfferCode({
message: 'Offer `code` must be unique.' message: 'Offer `code` must be unique.'
}); });
} }
this.changed.code.push(this.props.code); this.changed.code = this.props.code;
this.props.code = code; this.props.code = code;
} }
@ -197,7 +202,6 @@ class Offer {
message: 'Offer `name` must be unique.' message: 'Offer `name` must be unique.'
}); });
} }
this.changed.name.push(this.props.name);
this.props.name = name; this.props.name = name;
} }
@ -214,8 +218,8 @@ class Offer {
this.options = options; this.options = options;
/** @private */ /** @private */
this.changed = { this.changed = {
code: [], /** @type OfferCode */
name: [] code: null
}; };
} }