@haus-tech/campaign-price-plugin 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ ## 1.0.1
2
+
3
+ ### 🚀 Features
4
+
5
+ - optimize price resolution in campaign price plugin ([706bc2e](https://github.com/WeAreHausTech/haus-tech-vendure-plugins/commit/706bc2e))
6
+ - add index file for campaign price plugin ([d0123d7](https://github.com/WeAreHausTech/haus-tech-vendure-plugins/commit/d0123d7))
7
+ - add campaign price plugin for Vendure ([e6579e9](https://github.com/WeAreHausTech/haus-tech-vendure-plugins/commit/e6579e9))
8
+
9
+ ### 🩹 Fixes
10
+
11
+ - add TODO comment for tax support in campaign price label ([c6a7063](https://github.com/WeAreHausTech/haus-tech-vendure-plugins/commit/c6a7063))
12
+
13
+ # 1.0.0
14
+
15
+ ### 🚀 Features
16
+
17
+ - add campaign price plugin for Vendure ([e6579e9](https://github.com/WeAreHausTech/haus-tech-vendure-plugins/commit/e6579e9))
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ ---
2
+ name: campaign-price-plugin
3
+ title: Campaign Price Plugin
4
+ description: Vendure plugin that adds campaign pricing with an ordinaryPrice field for "was / now" display.
5
+ version: 1.0.0
6
+ tags: [vendure, plugin, campaign, price, sale]
7
+ ---
8
+
9
+ # Campaign Price Plugin
10
+
11
+ The **Campaign Price Plugin** is a Vendure plugin that lets you run campaigns and sales by setting a campaign price on product variant prices. When a campaign price is set, it is used as the selling price instead of the ordinary price. The plugin also exposes an `ordinaryPrice` field in the Shop API so storefronts can show “was X, now Y” pricing.
12
+
13
+ ## Functionality
14
+
15
+ - **Campaign price custom field** — Add a `campaignPrice` (integer) to `ProductVariantPrice`, editable per channel/currency in the Admin UI.
16
+ - **Price calculation strategy** — If a variant has a campaign price set and it is greater than zero, that price is used; otherwise the existing price calculation strategy is used.
17
+ - **Ordinary price in Shop API** — `ProductVariant`, `Product`, and `SearchResult` get an `ordinaryPrice` field so the storefront can display the original price alongside the current (possibly campaign) price.
18
+
19
+ ## Use Cases
20
+
21
+ - Time-limited sales or campaigns with a different price per channel/currency.
22
+ - Showing strikethrough “was X” and “now Y” prices on product and search pages.
23
+ - Running campaigns without changing the base price data; turn the campaign off by clearing the campaign price.
24
+
25
+ ## Installation
26
+
27
+ To install the `Campaign Price Plugin`, follow these steps:
28
+
29
+ 1. Install the plugin package:
30
+
31
+ ```bash
32
+ yarn add @haus-tech/campaign-price-plugin
33
+ ```
34
+
35
+ Or, if using npm:
36
+
37
+ ```bash
38
+ npm install @haus-tech/campaign-price-plugin
39
+ ```
40
+
41
+ 2. Add the plugin to your Vendure configuration in `vendure-config.ts`:
42
+
43
+ ```ts
44
+ import { CampaignPricePlugin } from '@haus-tech/campaign-price-plugin'
45
+
46
+ export const config = {
47
+ plugins: [CampaignPricePlugin],
48
+ }
49
+ ```
50
+
51
+ 3. Restart your Vendure server.
52
+
53
+ ## Usage
54
+
55
+ ### Admin UI
56
+
57
+ In the Admin UI, each product variant price has a **Campaign Price** field (per channel/currency). Set it to run a campaign; leave it empty or zero to use the ordinary price. The field uses the currency form input component.
58
+
59
+ ### Shop API
60
+
61
+ The plugin extends the Shop API so you can read both the current price (which may be the campaign price) and the ordinary price.
62
+
63
+ - **`ProductVariant.ordinaryPrice`** — `Int!` — The ordinary (pre-campaign) price for the variant.
64
+ - **`Product.ordinaryPrice`** — `SearchResultPrice!` — Min/max ordinary price across the product’s variants (single value or range).
65
+ - **`SearchResult.ordinaryPrice`** — `SearchResultPrice!` — Ordinary price for search results. Requires the default search plugin to index `product-ordinaryPriceMin` and `product-ordinaryPriceMax` if you use search; add these to your search index configuration if needed.
66
+
67
+ Example: show “was / now” on a variant:
68
+
69
+ ```graphql
70
+ query VariantPricing($id: ID!) {
71
+ productVariant(id: $id) {
72
+ id
73
+ price
74
+ priceWithTax
75
+ ordinaryPrice
76
+ }
77
+ }
78
+ ```
79
+
80
+ Example: product with variant price range:
81
+
82
+ ```graphql
83
+ query ProductPricing($id: ID!) {
84
+ product(id: $id) {
85
+ id
86
+ priceRange {
87
+ min
88
+ max
89
+ }
90
+ ordinaryPrice {
91
+ ... on SinglePrice {
92
+ value
93
+ }
94
+ ... on PriceRange {
95
+ min
96
+ max
97
+ }
98
+ }
99
+ }
100
+ }
101
+ ```
102
+
103
+ Use `price` / `priceRange` for the current selling price (campaign or ordinary) and `ordinaryPrice` for the original price in your “was X, now Y” UI.
104
+
105
+ ## Testing
106
+
107
+ 1. Run `yarn test` to execute the tests.
108
+ 2. Implement additional tests to cover your specific use cases.
109
+
110
+ ## Publish to NPM
111
+
112
+ 1. Make sure you are [logged in to NPM](https://docs.npmjs.com/cli/v9/commands/npm-login).
113
+ 2. Build the plugin:
114
+
115
+ ```bash
116
+ yarn build
117
+ ```
118
+
119
+ 3. Publish the plugin:
120
+
121
+ ```bash
122
+ yarn publish
123
+ ```
124
+
125
+ ## Resources
126
+
127
+ - [Vendure Plugin Documentation](https://www.vendure.io/docs/plugins/)
128
+ - [GraphQL Code Generator](https://the-guild.dev/graphql/codegen) for generating TypeScript types for custom GraphQL types.
129
+ - [Vendure Price Calculation](https://www.vendure.io/docs/products-stock/pricing/) for custom strategies
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@haus-tech/campaign-price-plugin",
3
+ "version": "1.0.2",
4
+ "description": "Campaign price plugin",
5
+ "author": "Haus Tech",
6
+ "repository": "https://github.com/WeAreHausTech/haus-tech-vendure-plugins",
7
+ "license": "MIT",
8
+ "engines": {
9
+ "node": ">=20.0.0"
10
+ },
11
+ "main": "src/index.js",
12
+ "types": "src/index.d.ts",
13
+ "scripts": {
14
+ "start": "yarn ts-node test/dev-server.ts"
15
+ },
16
+ "type": "commonjs"
17
+ }
@@ -0,0 +1 @@
1
+ export declare const apiExtensions: import("graphql").DocumentNode;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.apiExtensions = void 0;
7
+ const graphql_tag_1 = __importDefault(require("graphql-tag"));
8
+ exports.apiExtensions = (0, graphql_tag_1.default) `
9
+ extend type ProductVariant {
10
+ ordinaryPrice: Int!
11
+ }
12
+
13
+ extend type Product {
14
+ ordinaryPrice: SearchResultPrice!
15
+ }
16
+
17
+ extend type SearchResult {
18
+ ordinaryPrice: SearchResultPrice!
19
+ }
20
+ `;
21
+ //# sourceMappingURL=api-extensions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-extensions.js","sourceRoot":"","sources":["../../../../../packages/campaign-price-plugin/src/api/api-extensions.ts"],"names":[],"mappings":";;;;;;AAAA,8DAA6B;AAEhB,QAAA,aAAa,GAAG,IAAA,qBAAG,EAAA;;;;;;;;;;;;CAY/B,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { RequestContext, Product, ProductVariantService } from '@vendure/core';
2
+ import { SearchResultPrice } from '@vendure/common/lib/generated-shop-types';
3
+ export declare class CampaignPriceProductResolver {
4
+ private productVariantService;
5
+ constructor(productVariantService: ProductVariantService);
6
+ private resolvePrice;
7
+ ordinaryPrice(ctx: RequestContext, product: Product): Promise<SearchResultPrice>;
8
+ }
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.CampaignPriceProductResolver = void 0;
16
+ const graphql_1 = require("@nestjs/graphql");
17
+ const core_1 = require("@vendure/core");
18
+ let CampaignPriceProductResolver = class CampaignPriceProductResolver {
19
+ productVariantService;
20
+ constructor(productVariantService) {
21
+ this.productVariantService = productVariantService;
22
+ }
23
+ resolvePrice(min, max) {
24
+ if (min === undefined || max === undefined) {
25
+ return {
26
+ __typename: 'SinglePrice',
27
+ value: 0,
28
+ };
29
+ }
30
+ if (min === max) {
31
+ return {
32
+ __typename: 'SinglePrice',
33
+ value: min,
34
+ };
35
+ }
36
+ return {
37
+ __typename: 'PriceRange',
38
+ min,
39
+ max,
40
+ };
41
+ }
42
+ async ordinaryPrice(ctx, product) {
43
+ if (!product || !product.variants || !product.variants.length) {
44
+ return this.resolvePrice(0, 0);
45
+ }
46
+ // TODO: Cache the prices
47
+ const prices = await Promise.all(product.variants.map(async (variant) => {
48
+ if (!variant)
49
+ return 0;
50
+ const variantPrices = await this.productVariantService.getProductVariantPrices(ctx, variant.id);
51
+ return variantPrices?.[0]?.price || 0;
52
+ }));
53
+ const min = Math.min(...prices);
54
+ const max = Math.max(...prices);
55
+ return this.resolvePrice(min, max);
56
+ }
57
+ };
58
+ exports.CampaignPriceProductResolver = CampaignPriceProductResolver;
59
+ __decorate([
60
+ (0, graphql_1.ResolveField)('ordinaryPrice'),
61
+ __param(0, (0, core_1.Ctx)()),
62
+ __param(1, (0, graphql_1.Parent)()),
63
+ __metadata("design:type", Function),
64
+ __metadata("design:paramtypes", [core_1.RequestContext,
65
+ core_1.Product]),
66
+ __metadata("design:returntype", Promise)
67
+ ], CampaignPriceProductResolver.prototype, "ordinaryPrice", null);
68
+ exports.CampaignPriceProductResolver = CampaignPriceProductResolver = __decorate([
69
+ (0, graphql_1.Resolver)('Product'),
70
+ __metadata("design:paramtypes", [core_1.ProductVariantService])
71
+ ], CampaignPriceProductResolver);
72
+ //# sourceMappingURL=campaign-price-product.resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"campaign-price-product.resolver.js","sourceRoot":"","sources":["../../../../../packages/campaign-price-plugin/src/api/campaign-price-product.resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,6CAAgE;AAChE,wCAAmF;AAI5E,IAAM,4BAA4B,GAAlC,MAAM,4BAA4B;IACnB;IAApB,YAAoB,qBAA4C;QAA5C,0BAAqB,GAArB,qBAAqB,CAAuB;IAAG,CAAC;IAE5D,YAAY,CAAC,GAAY,EAAE,GAAY;QAC7C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC3C,OAAO;gBACL,UAAU,EAAE,aAAa;gBACzB,KAAK,EAAE,CAAC;aACT,CAAA;QACH,CAAC;QAED,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAChB,OAAO;gBACL,UAAU,EAAE,aAAa;gBACzB,KAAK,EAAE,GAAG;aACX,CAAA;QACH,CAAC;QAED,OAAO;YACL,UAAU,EAAE,YAAY;YACxB,GAAG;YACH,GAAG;SACJ,CAAA;IACH,CAAC;IAGK,AAAN,KAAK,CAAC,aAAa,CACV,GAAmB,EAChB,OAAgB;QAE1B,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC9D,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAChC,CAAC;QAED,yBAAyB;QACzB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YACrC,IAAI,CAAC,OAAO;gBAAE,OAAO,CAAC,CAAA;YACtB,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,uBAAuB,CAC5E,GAAG,EACH,OAAO,CAAC,EAAE,CACX,CAAA;YACD,OAAO,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAA;QACvC,CAAC,CAAC,CACH,CAAA;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAA;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAA;QAE/B,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACpC,CAAC;CACF,CAAA;AAnDY,oEAA4B;AA0BjC;IADL,IAAA,sBAAY,EAAC,eAAe,CAAC;IAE3B,WAAA,IAAA,UAAG,GAAE,CAAA;IACL,WAAA,IAAA,gBAAM,GAAE,CAAA;;qCADG,qBAAc;QACP,cAAO;;iEAsB3B;uCAlDU,4BAA4B;IADxC,IAAA,kBAAQ,EAAC,SAAS,CAAC;qCAEyB,4BAAqB;GADrD,4BAA4B,CAmDxC"}
@@ -0,0 +1,20 @@
1
+ import { SearchResult } from '@vendure/common/lib/generated-shop-types';
2
+ interface ExtendedSearchResult extends SearchResult {
3
+ 'product-ordinaryPriceMin'?: number;
4
+ 'product-ordinaryPriceMax'?: number;
5
+ }
6
+ export declare class CampaignPriceSearchResolver {
7
+ private resolvePrice;
8
+ ordinaryPrice(searchResult: ExtendedSearchResult): {
9
+ __typename: string;
10
+ value: number;
11
+ min?: undefined;
12
+ max?: undefined;
13
+ } | {
14
+ __typename: string;
15
+ min: number;
16
+ max: number;
17
+ value?: undefined;
18
+ };
19
+ }
20
+ export {};
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.CampaignPriceSearchResolver = void 0;
16
+ const graphql_1 = require("@nestjs/graphql");
17
+ let CampaignPriceSearchResolver = class CampaignPriceSearchResolver {
18
+ resolvePrice(min, max) {
19
+ if (min === undefined || max === undefined) {
20
+ return {
21
+ __typename: 'SinglePrice',
22
+ value: 0,
23
+ };
24
+ }
25
+ if (min === max) {
26
+ return {
27
+ __typename: 'SinglePrice',
28
+ value: min,
29
+ };
30
+ }
31
+ return {
32
+ __typename: 'PriceRange',
33
+ min,
34
+ max,
35
+ };
36
+ }
37
+ ordinaryPrice(searchResult) {
38
+ return this.resolvePrice(searchResult['product-ordinaryPriceMin'], searchResult['product-ordinaryPriceMax']);
39
+ }
40
+ };
41
+ exports.CampaignPriceSearchResolver = CampaignPriceSearchResolver;
42
+ __decorate([
43
+ (0, graphql_1.ResolveField)('ordinaryPrice'),
44
+ __param(0, (0, graphql_1.Parent)()),
45
+ __metadata("design:type", Function),
46
+ __metadata("design:paramtypes", [Object]),
47
+ __metadata("design:returntype", void 0)
48
+ ], CampaignPriceSearchResolver.prototype, "ordinaryPrice", null);
49
+ exports.CampaignPriceSearchResolver = CampaignPriceSearchResolver = __decorate([
50
+ (0, graphql_1.Resolver)('SearchResult')
51
+ ], CampaignPriceSearchResolver);
52
+ //# sourceMappingURL=campaign-price-search.resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"campaign-price-search.resolver.js","sourceRoot":"","sources":["../../../../../packages/campaign-price-plugin/src/api/campaign-price-search.resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,6CAAgE;AASzD,IAAM,2BAA2B,GAAjC,MAAM,2BAA2B;IAC9B,YAAY,CAAC,GAAY,EAAE,GAAY;QAC7C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC3C,OAAO;gBACL,UAAU,EAAE,aAAa;gBACzB,KAAK,EAAE,CAAC;aACT,CAAA;QACH,CAAC;QAED,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAChB,OAAO;gBACL,UAAU,EAAE,aAAa;gBACzB,KAAK,EAAE,GAAG;aACX,CAAA;QACH,CAAC;QAED,OAAO;YACL,UAAU,EAAE,YAAY;YACxB,GAAG;YACH,GAAG;SACJ,CAAA;IACH,CAAC;IAGD,aAAa,CAAW,YAAkC;QACxD,OAAO,IAAI,CAAC,YAAY,CACtB,YAAY,CAAC,0BAA0B,CAAC,EACxC,YAAY,CAAC,0BAA0B,CAAC,CACzC,CAAA;IACH,CAAC;CACF,CAAA;AA9BY,kEAA2B;AAwBtC;IADC,IAAA,sBAAY,EAAC,eAAe,CAAC;IACf,WAAA,IAAA,gBAAM,GAAE,CAAA;;;;gEAKtB;sCA7BU,2BAA2B;IADvC,IAAA,kBAAQ,EAAC,cAAc,CAAC;GACZ,2BAA2B,CA8BvC"}
@@ -0,0 +1,6 @@
1
+ import { RequestContext, ProductVariant, ProductVariantService } from '@vendure/core';
2
+ export declare class CampaignPriceVariantResolver {
3
+ private productVariantService;
4
+ constructor(productVariantService: ProductVariantService);
5
+ ordinaryPrice(ctx: RequestContext, productVariant: ProductVariant): Promise<number>;
6
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.CampaignPriceVariantResolver = void 0;
16
+ const graphql_1 = require("@nestjs/graphql");
17
+ const core_1 = require("@vendure/core");
18
+ let CampaignPriceVariantResolver = class CampaignPriceVariantResolver {
19
+ productVariantService;
20
+ constructor(productVariantService) {
21
+ this.productVariantService = productVariantService;
22
+ }
23
+ async ordinaryPrice(ctx, productVariant) {
24
+ // Prefer using the already-loaded price on the ProductVariant, if available,
25
+ // to avoid triggering an extra service call per variant (N+1 pattern).
26
+ const directPrice = productVariant.price;
27
+ if (typeof directPrice === 'number') {
28
+ return directPrice;
29
+ }
30
+ // TODO: Cache the prices
31
+ const variantPrices = await this.productVariantService.getProductVariantPrices(ctx, productVariant.id);
32
+ return variantPrices[0]?.price || 0;
33
+ }
34
+ };
35
+ exports.CampaignPriceVariantResolver = CampaignPriceVariantResolver;
36
+ __decorate([
37
+ (0, graphql_1.ResolveField)(),
38
+ __param(0, (0, core_1.Ctx)()),
39
+ __param(1, (0, graphql_1.Parent)()),
40
+ __metadata("design:type", Function),
41
+ __metadata("design:paramtypes", [core_1.RequestContext,
42
+ core_1.ProductVariant]),
43
+ __metadata("design:returntype", Promise)
44
+ ], CampaignPriceVariantResolver.prototype, "ordinaryPrice", null);
45
+ exports.CampaignPriceVariantResolver = CampaignPriceVariantResolver = __decorate([
46
+ (0, graphql_1.Resolver)('ProductVariant'),
47
+ __metadata("design:paramtypes", [core_1.ProductVariantService])
48
+ ], CampaignPriceVariantResolver);
49
+ //# sourceMappingURL=campaign-price-variant.resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"campaign-price-variant.resolver.js","sourceRoot":"","sources":["../../../../../packages/campaign-price-plugin/src/api/campaign-price-variant.resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,6CAAgE;AAChE,wCAA0F;AAGnF,IAAM,4BAA4B,GAAlC,MAAM,4BAA4B;IACnB;IAApB,YAAoB,qBAA4C;QAA5C,0BAAqB,GAArB,qBAAqB,CAAuB;IAAG,CAAC;IAG9D,AAAN,KAAK,CAAC,aAAa,CACV,GAAmB,EAChB,cAA8B;QAExC,6EAA6E;QAC7E,uEAAuE;QACvE,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAA;QACxC,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;YACpC,OAAO,WAAW,CAAA;QACpB,CAAC;QAED,yBAAyB;QACzB,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,uBAAuB,CAC5E,GAAG,EACH,cAAc,CAAC,EAAE,CAClB,CAAA;QAED,OAAO,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAA;IACrC,CAAC;CACF,CAAA;AAvBY,oEAA4B;AAIjC;IADL,IAAA,sBAAY,GAAE;IAEZ,WAAA,IAAA,UAAG,GAAE,CAAA;IACL,WAAA,IAAA,gBAAM,GAAE,CAAA;;qCADG,qBAAc;QACA,qBAAc;;iEAgBzC;uCAtBU,4BAA4B;IADxC,IAAA,kBAAQ,EAAC,gBAAgB,CAAC;qCAEkB,4BAAqB;GADrD,4BAA4B,CAuBxC"}
@@ -0,0 +1,2 @@
1
+ export declare class CampaignPricePlugin {
2
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.CampaignPricePlugin = void 0;
10
+ const core_1 = require("@vendure/core");
11
+ const campaign_price_strategy_1 = require("./strategy/campaign-price.strategy");
12
+ const api_extensions_1 = require("./api/api-extensions");
13
+ const campaign_price_variant_resolver_1 = require("./api/campaign-price-variant.resolver");
14
+ const campaign_price_product_resolver_1 = require("./api/campaign-price-product.resolver");
15
+ const campaign_price_search_resolver_1 = require("./api/campaign-price-search.resolver");
16
+ let CampaignPricePlugin = class CampaignPricePlugin {
17
+ };
18
+ exports.CampaignPricePlugin = CampaignPricePlugin;
19
+ exports.CampaignPricePlugin = CampaignPricePlugin = __decorate([
20
+ (0, core_1.VendurePlugin)({
21
+ imports: [core_1.PluginCommonModule],
22
+ shopApiExtensions: {
23
+ schema: api_extensions_1.apiExtensions,
24
+ resolvers: [
25
+ campaign_price_variant_resolver_1.CampaignPriceVariantResolver,
26
+ campaign_price_product_resolver_1.CampaignPriceProductResolver,
27
+ campaign_price_search_resolver_1.CampaignPriceSearchResolver,
28
+ ],
29
+ },
30
+ configuration: (config) => {
31
+ config.customFields.ProductVariantPrice.push({
32
+ name: 'campaignPrice',
33
+ type: 'int',
34
+ nullable: true,
35
+ public: true,
36
+ ui: { component: 'currency-form-input' },
37
+ label: [
38
+ { languageCode: core_1.LanguageCode.en, value: 'Campaign Price' },
39
+ { languageCode: core_1.LanguageCode.sv, value: 'Kampanjpris (inkl. moms)' }, // TODO: We need to support prices without tax?
40
+ ],
41
+ });
42
+ config.catalogOptions.productVariantPriceCalculationStrategy = new campaign_price_strategy_1.CampaignPriceStrategy(config.catalogOptions.productVariantPriceCalculationStrategy);
43
+ return config;
44
+ },
45
+ })
46
+ ], CampaignPricePlugin);
47
+ //# sourceMappingURL=campaign-price.plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"campaign-price.plugin.js","sourceRoot":"","sources":["../../../../packages/campaign-price-plugin/src/campaign-price.plugin.ts"],"names":[],"mappings":";;;;;;;;;AAAA,wCAA+E;AAC/E,gFAA0E;AAC1E,yDAAoD;AACpD,2FAAoF;AACpF,2FAAoF;AACpF,yFAAkF;AAgC3E,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;CAAG,CAAA;AAAtB,kDAAmB;8BAAnB,mBAAmB;IA9B/B,IAAA,oBAAa,EAAC;QACb,OAAO,EAAE,CAAC,yBAAkB,CAAC;QAC7B,iBAAiB,EAAE;YACjB,MAAM,EAAE,8BAAa;YACrB,SAAS,EAAE;gBACT,8DAA4B;gBAC5B,8DAA4B;gBAC5B,4DAA2B;aAC5B;SACF;QACD,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE;YACxB,MAAM,CAAC,YAAY,CAAC,mBAAmB,CAAC,IAAI,CAAC;gBAC3C,IAAI,EAAE,eAAe;gBACrB,IAAI,EAAE,KAAK;gBACX,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,IAAI;gBACZ,EAAE,EAAE,EAAE,SAAS,EAAE,qBAAqB,EAAE;gBACxC,KAAK,EAAE;oBACL,EAAE,YAAY,EAAE,mBAAY,CAAC,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE;oBAC1D,EAAE,YAAY,EAAE,mBAAY,CAAC,EAAE,EAAE,KAAK,EAAE,0BAA0B,EAAE,EAAE,+CAA+C;iBACtH;aACF,CAAC,CAAA;YAEF,MAAM,CAAC,cAAc,CAAC,sCAAsC,GAAG,IAAI,+CAAqB,CACtF,MAAM,CAAC,cAAc,CAAC,sCAAsC,CAC7D,CAAA;YAED,OAAO,MAAM,CAAA;QACf,CAAC;KACF,CAAC;GACW,mBAAmB,CAAG"}
package/src/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './campaign-price.plugin';
package/src/index.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./campaign-price.plugin"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/campaign-price-plugin/src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0DAAuC"}
@@ -0,0 +1,11 @@
1
+ import { ProductVariantPriceCalculationStrategy, PriceCalculationResult, ProductVariantPriceCalculationArgs } from '@vendure/core';
2
+ declare module '@vendure/core/dist/entity/custom-entity-fields' {
3
+ interface CustomProductVariantPriceFields {
4
+ campaignPrice: number;
5
+ }
6
+ }
7
+ export declare class CampaignPriceStrategy implements ProductVariantPriceCalculationStrategy {
8
+ private existingStrategy;
9
+ constructor(existingStrategy: ProductVariantPriceCalculationStrategy);
10
+ calculate(args: ProductVariantPriceCalculationArgs): Promise<PriceCalculationResult>;
11
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.CampaignPriceStrategy = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ let CampaignPriceStrategy = class CampaignPriceStrategy {
15
+ existingStrategy;
16
+ constructor(existingStrategy) {
17
+ this.existingStrategy = existingStrategy;
18
+ }
19
+ async calculate(args) {
20
+ const { productVariant } = args;
21
+ const variantPrices = productVariant.productVariantPrices;
22
+ const campaignPrice = variantPrices[0]?.customFields?.campaignPrice;
23
+ if (campaignPrice != null && campaignPrice > 0) {
24
+ return {
25
+ price: campaignPrice,
26
+ priceIncludesTax: true,
27
+ };
28
+ }
29
+ return this.existingStrategy.calculate(args);
30
+ }
31
+ };
32
+ exports.CampaignPriceStrategy = CampaignPriceStrategy;
33
+ exports.CampaignPriceStrategy = CampaignPriceStrategy = __decorate([
34
+ (0, common_1.Injectable)(),
35
+ __metadata("design:paramtypes", [Object])
36
+ ], CampaignPriceStrategy);
37
+ //# sourceMappingURL=campaign-price.strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"campaign-price.strategy.js","sourceRoot":"","sources":["../../../../../packages/campaign-price-plugin/src/strategy/campaign-price.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA2C;AAcpC,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IACZ;IAApB,YAAoB,gBAAwD;QAAxD,qBAAgB,GAAhB,gBAAgB,CAAwC;IAAG,CAAC;IAEhF,KAAK,CAAC,SAAS,CAAC,IAAwC;QACtD,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAA;QAE/B,MAAM,aAAa,GAAG,cAAc,CAAC,oBAAoB,CAAA;QACzD,MAAM,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,aAAa,CAAA;QAEnE,IAAI,aAAa,IAAI,IAAI,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;YAC/C,OAAO;gBACL,KAAK,EAAE,aAAa;gBACpB,gBAAgB,EAAE,IAAI;aACvB,CAAA;QACH,CAAC;QAED,OAAO,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IAC9C,CAAC;CACF,CAAA;AAlBY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;;GACA,qBAAqB,CAkBjC"}