Answers.Body: <p>Options #1 and #3 are the two options you'll want to decide between, and you've hit the nail on the head in terms of the pros and cons of each.</p>
  <p>If a discount code being deleted / modified poses a danger to you codebase, then the price adjustment is cleaner.</p>
  <p>If you can code defensively, always checking that the discount you're expecting exists before trying to call it, you can use option #1 and know that deleting that discount from the CMS (or forgetting to add it, and spell it correctly on deployment) is an existing failure point.</p>
  <p>The answer comes down to what yourself and your client are comfortable with in terms of risk.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-02T09:58:19.283Z
Answers.Text: Thank you for your insights! In regards to code defensively, is there any way to uniquely refer to a specific discount to check if it exists or not? They don't have handles and their IDs are specific to each environment. I guess I can only iterate through existing discounts to check if the 50% discount exists? Or just build everything in a generic way so that it works with all kinds of discounts?
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-02T18:30:11.763Z
Answers.Text: I'm always a fan of setting up generic approaches that set you up for future use cases and also give CMS managers expectable outcomes to the changes they make. That said, if you needed to do a check you'd want to do `craft.commerce.discounts.getDiscountByCode('CODE')` to see if it exists (not null) and to use for any comparisons.
Answers.UserDisplayName: cherrykoda
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-03T09:10:31.400Z
Answers.Text: @cherrycode Thanks! I'll see how we can build this function in a way that works with any discounts but also integrate the member discount into the interface. But the last part won't work, as the member discount is just based on a specific user group – there's no discount code to be applied.
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-03T17:55:36.450Z
Answers.Text: Oh, that's far trickier. I'll poke around the docs but I'm not sure if there will be a consistently good way to always get the right one.
Answers.UserDisplayName: cherrykoda
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-03T19:52:15.850Z
Answers.Text: Yeah I had a look as well, doesn't seem like there's a way to uniquely identify specific discount. I guess that makes sense since they're designed to be "ephemeral" in a sense. Maybe I'll look into writing an adjuster instead on monday.
Answers.UserDisplayName: MoritzLost
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-02T04:56:30.357Z
Answers.LastActivityDate: 2023-03-02T04:56:30.357Z
Answers.UserDisplayName: cherrykoda
Body: <p>I'm working on a Craft Commerce project where users can register for paid events. The events have a different price for members and non-members of the organization the site belongs to. I'm not sure what the best way to represent this member discount is. My ideas:</p>
  <ol>
  <li>Create a discount that takes a fixed amount or percentage amount off, and use a <em>Match Customer</em> rule to only apply to users in the <em>Member</em> group. However, I need to build this discount into the system into several functions and templates, and it looks like you're not supposed to build around the assumption that a specific discount will always exist. Discounts aren't tracked in the project config, so a specific discount may or may not exist on the production site. I can use a migration to create the discount, but it can still be deleted. Discounts also don't have handles, so there isn't even a way to fetch a specific discount in a template to see whether it exists. I also need to show prices for members and non-members without the context of a cart, and there doesn't seem a simple way to do that, since discounts can only apply to orders or carts. Feels like this solution would require a lot of small hacks to deeply integrate into templates and functionality, doesn't feel like the best solution.</li>
  <li>Use product variants – each event gets a variant for members and one for non-members. I could use hooks to ensure only members can buy the member-only variant. However, this would require editors to manually add both variants for all events, which is error-prone and a lot of unnecessary work.</li>
  <li>Write a custom adjuster that discounts events for members automatically. This feels like the cleanest solution, but feels like a lot of work for a rather 'basic' requirement. I only want to try that once I'm sure there's no better solution.</li>
  <li>Use the <a href="https://verbb.io/craft-plugins/events/docs/feature-tour/event-types" rel="nofollow noreferrer">Events</a> plugin, which supports creating different tickets. This would probably work, but has some other issues that prevent me from using it (most prominently that it's still in beta for Craft 4).</li>
  </ol>
  <p>Which of those approaches is the best? Is there a simpler solution that I'm not seeing? I think discounts are probably the intended way to handle this scenario, but how can I handle the problems mentioned above in this case?</p>
  
Tags: <plugin-craftcommerce><discounts><commerce4>
Title: How to represent member discount for Commerce products?
ThreadText: # How to represent member discount for Commerce products?
  
  (Asked by: username_0 on 2023-03-01)
  
  I'm working on a Craft Commerce project where users can register for paid events. The events have a different price for members and non-members of the organization the site belongs to. I'm not sure what the best way to represent this member discount is. My ideas:
  
  1. Create a discount that takes a fixed amount or percentage amount off, and use a *Match Customer* rule to only apply to users in the *Member* group. However, I need to build this discount into the system into several functions and templates, and it looks like you're not supposed to build around the assumption that a specific discount will always exist. Discounts aren't tracked in the project config, so a specific discount may or may not exist on the production site. I can use a migration to create the discount, but it can still be deleted. Discounts also don't have handles, so there isn't even a way to fetch a specific discount in a template to see whether it exists. I also need to show prices for members and non-members without the context of a cart, and there doesn't seem a simple way to do that, since discounts can only apply to orders or carts. Feels like this solution would require a lot of small hacks to deeply integrate into templates and functionality, doesn't feel like the best solution.
  2. Use product variants – each event gets a variant for members and one for non-members. I could use hooks to ensure only members can buy the member-only variant. However, this would require editors to manually add both variants for all events, which is error-prone and a lot of unnecessary work.
  3. Write a custom adjuster that discounts events for members automatically. This feels like the cleanest solution, but feels like a lot of work for a rather 'basic' requirement. I only want to try that once I'm sure there's no better solution.
  4. Use the [Events](https://verbb.io/craft-plugins/events/docs/feature-tour/event-types) plugin, which supports creating different tickets. This would probably work, but has some other issues that prevent me from using it (most prominently that it's still in beta for Craft 4).
  
  Which of those approaches is the best? Is there a simpler solution that I'm not seeing? I think discounts are probably the intended way to handle this scenario, but how can I handle the problems mentioned above in this case?
  
  **Tags:** plugin-craftcommerce, discounts, commerce4
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2023-03-02. Score: 5 | Accepted answer
  
  Options #1 and #3 are the two options you'll want to decide between, and you've hit the nail on the head in terms of the pros and cons of each.
  
  If a discount code being deleted / modified poses a danger to you codebase, then the price adjustment is cleaner.
  
  If you can code defensively, always checking that the discount you're expecting exists before trying to call it, you can use option #1 and know that deleting that discount from the CMS (or forgetting to add it, and spell it correctly on deployment) is an existing failure point.
  
  The answer comes down to what yourself and your client are comfortable with in terms of risk.
  
  > **Comments:**
  > **username_0**: Thank you for your insights! In regards to code defensively, is there any way to uniquely refer to a specific discount to check if it exists or not? They don't have handles and their IDs are specific to each environment. I guess I can only iterate through existing discounts to check if the 50% discount exists? Or just build everything in a generic way so that it works with all kinds of discounts?  
  > **username_1**: I'm always a fan of setting up generic approaches that set you up for future use cases and also give CMS managers expectable outcomes to the changes they make. That said, if you needed to do a check you'd want to do `craft.commerce.discounts.getDiscountByCode('CODE')` to see if it exists (not null) and to use for any comparisons.  
  > **username_0**: @cherrycode Thanks! I'll see how we can build this function in a way that works with any discounts but also integrate the member discount into the interface. But the last part won't work, as the member discount is just based on a specific user group – there's no discount code to be applied.  
  > **username_1**: Oh, that's far trickier. I'll poke around the docs but I'm not sure if there will be a consistently good way to always get the right one.  
  > **username_0**: Yeah I had a look as well, doesn't seem like there's a way to uniquely identify specific discount. I guess that makes sense since they're designed to be "ephemeral" in a sense. Maybe I'll look into writing an adjuster instead on monday.  
  
  ---
  
  