Skip to content

Commit 684b2af

Browse files
kaigosselcyl3x
andauthored
ECTO-2133 - Implement yearly rent variant (#116) (#118)
* ECTO-2133 - Implement yearly rent variant (#116) * ECTO-2150 - Add yearly variant to listing * ECTO-2151 - Add yearly variant to detail page * ECTO-2136 - Add yearly variant to checkout modal * fix: open extension buy modal (#121) --------- Co-authored-by: Michel <m.bade@shopware.com>
1 parent 06f95c6 commit 684b2af

File tree

18 files changed

+1701
-817
lines changed

18 files changed

+1701
-817
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "swag/swag-extension-store",
3-
"version": "3.2.0",
3+
"version": "3.3.0",
44
"description": "SWAG Extension Store",
55
"type": "shopware-platform-plugin",
66
"license": "MIT",

src/Resources/app/administration/src/module/sw-extension-store/component/sw-extension-buy-modal/index.js

Lines changed: 170 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export default {
1111

1212
inject: [
1313
'shopwareExtensionService',
14+
'extensionStoreService',
1415
'extensionStoreLicensesService'
1516
],
1617

@@ -48,28 +49,7 @@ export default {
4849
},
4950

5051
computed: {
51-
recommendedVariants() {
52-
return this.shopwareExtensionService.orderVariantsByRecommendation(this.extension.variants);
53-
},
54-
55-
selectedVariant() {
56-
return this.extension.variants.find((variant) => {
57-
return variant.id === this.selectedVariantId;
58-
});
59-
},
60-
61-
todayPlusOneMonth() {
62-
const date = new Date();
63-
date.setMonth(date.getMonth() + 1);
64-
65-
return date;
66-
},
67-
68-
dateFilter() {
69-
return Utils.format.date;
70-
},
71-
72-
formattedPrice() {
52+
actualPrice() {
7353
const cartPosition = this.cart && this.cart.positions && this.cart.positions[0];
7454
const netPrice = cartPosition && cartPosition.netPrice;
7555

@@ -82,38 +62,89 @@ export default {
8262
}
8363

8464
return Utils.format.currency(
85-
this.shopwareExtensionService.getPriceFromVariant(this.selectedVariant),
65+
this.extensionStoreService.getPriceFromVariant(this.selectedVariant),
8666
'EUR'
8767
);
8868
},
8969

90-
trialPrice() {
91-
return this.renderPrice(0);
70+
actualPriceSnippet() {
71+
if (this.extensionStoreService.isVariantOfTypeFree(this.selectedVariant)) {
72+
return 'sw-extension-store.general.labelFree';
73+
}
74+
75+
if (this.extensionStoreService.isVariantOfTypeBuy(this.selectedVariant)) {
76+
return 'sw-extension-store.general.labelPriceOneTime';
77+
}
78+
79+
const cartPosition = this.cart && this.cart.positions && this.cart.positions[0];
80+
const netPrice = cartPosition && cartPosition.netPrice;
81+
82+
if (netPrice && cartPosition && cartPosition.firstMonthFree) {
83+
return 'sw-extension-store.general.labelPriceFirstMonth';
84+
}
85+
86+
if (this.isRentDurationYearly(this.selectedVariant)) {
87+
return 'sw-extension-store.general.labelPricePerYear';
88+
}
89+
90+
return 'sw-extension-store.general.labelPricePerMonth';
9291
},
9392

94-
purchaseButtonLabel() {
95-
switch (this.selectedVariant.type) {
96-
case this.shopwareExtensionService.EXTENSION_VARIANT_TYPES.FREE:
97-
return this.$tc('sw-extension-store.component.sw-extension-buy-modal.purchaseButtonsLabels.free');
93+
finalPriceSnippet() {
94+
if (this.isRentDurationYearly(this.selectedVariant)) {
95+
return 'sw-extension-store.buy-modal.rent.yearly.finalPrice';
96+
}
9897

99-
case this.shopwareExtensionService.EXTENSION_VARIANT_TYPES.RENT:
100-
return this.$tc('sw-extension-store.component.sw-extension-buy-modal.purchaseButtonsLabels.rent');
98+
return 'sw-extension-store.buy-modal.rent.monthly.finalPrice';
99+
},
100+
101+
recommendedVariants() {
102+
return this.extensionStoreService.orderVariantsByRentDuration(this.extension.variants);
103+
},
104+
105+
selectedVariant() {
106+
return this.extension.variants.find((variant) => {
107+
return variant.id === this.selectedVariantId;
108+
});
109+
},
110+
111+
dateFilter() {
112+
return Utils.format.date;
113+
},
114+
115+
purchaseButtonLabel() {
116+
if (this.isVariantOfTypeFree(this.selectedVariant)) {
117+
return this.$t('sw-extension-store.component.sw-extension-buy-modal.purchaseButtonsLabels.free');
118+
}
101119

102-
case this.shopwareExtensionService.EXTENSION_VARIANT_TYPES.BUY:
103-
default:
104-
return this.$tc('sw-extension-store.component.sw-extension-buy-modal.purchaseButtonsLabels.buy');
120+
if (this.isVariantOfTypeRent(this.selectedVariant)) {
121+
return this.$t('sw-extension-store.component.sw-extension-buy-modal.purchaseButtonsLabels.rent');
105122
}
123+
124+
return this.$t('sw-extension-store.component.sw-extension-buy-modal.purchaseButtonsLabels.buy');
106125
},
107126

108127
vatIncludedClasses() {
109128
return {
110-
'is--hidden': this.selectedVariant.type === this.shopwareExtensionService.EXTENSION_VARIANT_TYPES.FREE
129+
'is--hidden': this.isVariantOfTypeFree(this.selectedVariant)
111130
};
112131
},
113132

133+
renewalDate() {
134+
const date = new Date();
135+
136+
if (this.isRentDurationMonthly(this.selectedVariant)) {
137+
date.setMonth(date.getMonth() + 1);
138+
} else {
139+
date.setMonth(date.getMonth() + 12);
140+
}
141+
142+
return date;
143+
},
144+
114145
renewalDateClasses() {
115146
return {
116-
'is--hidden': this.selectedVariant.type !== this.shopwareExtensionService.EXTENSION_VARIANT_TYPES.RENT
147+
'is--hidden': this.isVariantOfTypeRent(this.selectedVariant) === false
117148
};
118149
},
119150

@@ -255,6 +286,108 @@ export default {
255286
this.$emit('modal-close');
256287
},
257288

289+
getDiscountClasses(variant) {
290+
return {
291+
'is--discounted': this.hasActiveDiscount(variant)
292+
};
293+
},
294+
295+
getVariantPrice(variant) {
296+
return this.extensionStoreService.getCalculatedPrice(variant);
297+
},
298+
299+
getVariantPriceSnippet(variant) {
300+
return this.extensionStoreService.getPriceSnippetForVariant(variant);
301+
},
302+
303+
getVariantDiscountInformationSnippet(variant) {
304+
if (this.isRentDurationYearly(variant)) {
305+
return 'sw-extension-store.buy-modal.rent.yearly.discountInformation';
306+
}
307+
308+
return 'sw-extension-store.buy-modal.rent.monthly.discountInformation';
309+
},
310+
311+
getVariantCancellationInformationSnippet(variant) {
312+
if (this.isRentDurationYearly(variant)) {
313+
return 'sw-extension-store.buy-modal.rent.yearly.cancellationInformation';
314+
}
315+
316+
return 'sw-extension-store.buy-modal.rent.monthly.cancellationInformation';
317+
},
318+
319+
getVariantClasses(variant) {
320+
return {
321+
'is--monthly': this.isRentDurationMonthly(variant),
322+
'is--yearly': this.isRentDurationYearly(variant)
323+
};
324+
},
325+
326+
getVariantBadgeClasses(variant) {
327+
return {
328+
'sw-extension-buy-modal__variants-card-badge-discounted': this.hasActiveDiscount(variant),
329+
'is--monthly': this.isRentDurationMonthly(variant),
330+
'is--yearly': this.isRentDurationYearly(variant)
331+
};
332+
},
333+
334+
getVariantBadgeSavings(variant) {
335+
const monthlyVariant = this.extension.variants.find((v) => {
336+
return this.extensionStoreService.isRentDurationMonthly(v);
337+
});
338+
339+
if (!monthlyVariant) {
340+
return 0;
341+
}
342+
343+
const monthlyNetPrice = monthlyVariant.netPrice;
344+
const variantNetPrice = variant.netPrice;
345+
const variantDuration = variant.duration;
346+
347+
const hasSaving = variantNetPrice !== (monthlyNetPrice * variantDuration);
348+
const hasDiscount = this.hasActiveDiscount(variant);
349+
350+
let savingsPercentage = 0;
351+
352+
if (hasSaving && hasDiscount === false) {
353+
savingsPercentage = 100 * (1 - variantNetPrice / (monthlyNetPrice * variantDuration));
354+
} else if (hasSaving === false && hasDiscount) {
355+
savingsPercentage = 100 * (1 - variant.discountCampaign.discountedPrice / variant.netPrice);
356+
} else if (hasSaving && hasDiscount) {
357+
const savingPercentage = 100 * (1 - variantNetPrice / (monthlyNetPrice * variantDuration));
358+
const discountPercentage =
359+
100 * (1 - variant.discountCampaign.discountedPrice / (monthlyNetPrice * variantDuration));
360+
361+
savingsPercentage = discountPercentage - savingPercentage;
362+
}
363+
364+
return savingsPercentage.toFixed(2).replace(/\.00$/, '');
365+
},
366+
367+
hasActiveDiscount(variant) {
368+
return this.extensionStoreService.isVariantDiscounted(variant);
369+
},
370+
371+
isRentDurationMonthly(variant) {
372+
return this.extensionStoreService.isRentDurationMonthly(variant);
373+
},
374+
375+
isRentDurationYearly(variant) {
376+
return this.extensionStoreService.isRentDurationYearly(variant);
377+
},
378+
379+
isVariantOfTypeFree(variant) {
380+
return this.extensionStoreService.isVariantOfTypeFree(variant);
381+
},
382+
383+
isVariantOfTypeBuy(variant) {
384+
return this.extensionStoreService.isVariantOfTypeBuy(variant);
385+
},
386+
387+
isVariantOfTypeRent(variant) {
388+
return this.extensionStoreService.isVariantOfTypeRent(variant);
389+
},
390+
258391
setSelectedVariantId(variantId) {
259392
if (this.isLoading) {
260393
return;
@@ -273,10 +406,6 @@ export default {
273406
this.setSelectedVariantId(variant.id);
274407
},
275408

276-
variantRecommendation(variant) {
277-
return this.shopwareExtensionService.mapVariantToRecommendation(variant);
278-
},
279-
280409
async purchaseExtension() {
281410
this.isLoading = true;
282411

@@ -325,41 +454,18 @@ export default {
325454
}
326455
},
327456

328-
getDiscountClasses(variant) {
329-
return {
330-
'is--discounted': this.hasDiscount(variant)
331-
};
332-
},
333-
334-
hasDiscount(variant) {
335-
const campaign = variant.discountCampaign;
336-
return campaign
337-
&& new Date(Date.parse(campaign.startDate)) < (new Date())
338-
&& new Date(Date.parse(campaign.endDate)) >= (new Date());
339-
},
340-
341457
renderPrice(price) {
342458
return Utils.format.currency(price, 'EUR');
343459
},
344460

345461
renderBuyPrice(variant) {
346-
if (this.hasDiscount(variant)) {
462+
if (this.hasActiveDiscount(variant)) {
347463
return this.renderPrice(variant.discountCampaign.discountedPrice);
348464
}
349465

350466
return this.renderPrice(variant.netPrice);
351467
},
352468

353-
getDiscountPrice(variant) {
354-
return variant.discountCampaign ? this.renderPrice(variant.discountCampaign.discountedPrice) : this.trialPrice;
355-
},
356-
357-
getDiscountEnds(variant) {
358-
return Utils.format.date(
359-
variant.discountCampaign ? new Date(Date.parse(variant.discountCampaign.endDate)) : null
360-
);
361-
},
362-
363469
handleErrors(error) {
364470
this.showExtensionErrors(error);
365471
},
@@ -410,17 +516,6 @@ export default {
410516
});
411517
},
412518

413-
legalTextForVariant(variant) {
414-
if (!variant || !variant.legalText) {
415-
return null;
416-
}
417-
418-
return this.$sanitize(variant.legalText, {
419-
ALLOWED_TAGS: ['a', 'b', 'i', 'u', 'br', 'strong', 'p', 'br'],
420-
ALLOWED_ATTR: ['href', 'target', 'rel']
421-
});
422-
},
423-
424519
openPrivacyModal() {
425520
this.showPrivacyModal = true;
426521
},

0 commit comments

Comments
 (0)