mirror of
https://github.com/foomo/shop.git
synced 2025-10-16 12:35:39 +00:00
Feature: voucher cumulation (#14)
* enable optional cumulation of multiple regular vouchers (overruling best option rule) // fix bug where vouchers could falsely be cumulated when pricerule is identical // add unit tests * fix pre-filtering of vouchers * minor cleanup * refactor: remove access to global test data from promo cumulation tests // add test for employee disscount * feat: ExcludeAlreadyDiscountedItemsForVoucher does no longer apply to discounts with TypePromotionCustomer * update unit tests for promo cumulation * update unit tests for promo cumulation * update pricerule cumulation tests * pricerules: reimplement test for BuyXPayY * add more tests for pricerules
This commit is contained in:
parent
dc4811e002
commit
18e788cf8d
@ -57,6 +57,9 @@ func previouslyAppliedExclusionInPlace(rule *PriceRule, orderDiscountsForPositio
|
||||
previouslyAppliedExclusion := false
|
||||
|
||||
if rule.Type == TypePromotionCustomer || rule.Type == TypePromotionProduct || rule.Type == TypeVoucher {
|
||||
if rule.Type == TypeVoucher && rule.CumulateWithOtherVouchers {
|
||||
return false
|
||||
}
|
||||
if calculationParameters.bestOptionCustomeProductRulePerItem != nil {
|
||||
if bestRuleID, ok := calculationParameters.bestOptionCustomeProductRulePerItem[itemID]; ok {
|
||||
if rule.ID == bestRuleID {
|
||||
|
||||
@ -243,18 +243,52 @@ func ApplyDiscounts(articleCollection *ArticleCollection, existingDiscounts Orde
|
||||
orderDiscounts = calculateRule(orderDiscounts, priceRulePair, calculationParameters)
|
||||
}
|
||||
|
||||
// prepare step 2: filter vouchers
|
||||
// Make sure only one voucher per promo is set, unless CumulateWithOtherVouchers is true (bonus vouchers are not filtered)
|
||||
// (There is a bug in the best option calculation which applies multiple vouchers to the same item when voucher is from the same promo. This should fix it)
|
||||
voucherCodesTmp := []string{}
|
||||
priceruleIDs := map[string]bool{}
|
||||
for _, voucherCode := range voucherCodes {
|
||||
voucherVo, voucherPriceRule, err := GetVoucherAndPriceRule(voucherCode, customProvider)
|
||||
if voucherVo == nil {
|
||||
//log.Println("voucher not found for code: " + voucherCode + " in " + "priceRule.ApplyDiscounts")
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
log.Println("skipping voucher "+voucherCode, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// bonus vouchers are not being filtered
|
||||
if voucherPriceRule.Type == TypeBonusVoucher {
|
||||
voucherCodesTmp = append(voucherCodesTmp, voucherCode)
|
||||
continue
|
||||
}
|
||||
|
||||
// just to be safe
|
||||
if voucherPriceRule.Type != TypeVoucher {
|
||||
continue
|
||||
}
|
||||
if priceruleIDs[voucherPriceRule.ID] && !voucherPriceRule.CumulateWithOtherVouchers {
|
||||
continue // we already have a voucher for that promo
|
||||
}
|
||||
|
||||
voucherCodesTmp = append(voucherCodesTmp, voucherCode)
|
||||
priceruleIDs[voucherPriceRule.ID] = true
|
||||
}
|
||||
// replace vouchers with filtered ones
|
||||
voucherCodes = voucherCodesTmp
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
// vouchers: step 2
|
||||
// find the vouchers and voucher rules
|
||||
// find applicable pricerules of type TypeVoucher for
|
||||
bonusVoucherCodes := []string{}
|
||||
// step 2: vouchers where best option per items applies (CumulateWithOtherVouchers == false)
|
||||
if len(voucherCodes) > 0 {
|
||||
var ruleVoucherPairsStep2 []RuleVoucherPair
|
||||
for _, voucherCode := range voucherCodes {
|
||||
if len(voucherCode) > 0 {
|
||||
voucherVo, voucherPriceRule, err := GetVoucherAndPriceRule(voucherCode, customProvider)
|
||||
if voucherVo == nil {
|
||||
log.Println("voucher not found for code: " + voucherCode + " in " + "priceRule.ApplyDiscounts")
|
||||
continue
|
||||
//log.Println("voucher not found for code: " + voucherCode + " in " + "priceRule.ApplyDiscounts")
|
||||
}
|
||||
if err != nil {
|
||||
log.Println("skipping voucher "+voucherCode, err)
|
||||
@ -262,9 +296,11 @@ func ApplyDiscounts(articleCollection *ArticleCollection, existingDiscounts Orde
|
||||
}
|
||||
|
||||
if voucherPriceRule.Type != TypeVoucher {
|
||||
log.Println("skipping voucher "+voucherCode+" with type Voucher", err)
|
||||
bonusVoucherCodes = append(bonusVoucherCodes, voucherCode)
|
||||
continue
|
||||
continue // bonus vouchers are handled later in separate step
|
||||
}
|
||||
|
||||
if voucherPriceRule.CumulateWithOtherVouchers {
|
||||
continue // voucher will be applied in next step
|
||||
}
|
||||
|
||||
//check if rule is valid
|
||||
@ -312,6 +348,69 @@ func ApplyDiscounts(articleCollection *ArticleCollection, existingDiscounts Orde
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
// step 2.1: vouchers which are applied on top of other vouchers (CumulateWithOtherVouchers == true)
|
||||
if len(voucherCodes) > 0 {
|
||||
var ruleVoucherPairsStep21 []RuleVoucherPair
|
||||
for _, voucherCode := range voucherCodes {
|
||||
if len(voucherCode) > 0 {
|
||||
voucherVo, voucherPriceRule, err := GetVoucherAndPriceRule(voucherCode, customProvider)
|
||||
if voucherVo == nil {
|
||||
//log.Println("voucher not found for code: " + voucherCode + " in " + "priceRule.ApplyDiscounts")
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
log.Println("skipping voucher "+voucherCode, err)
|
||||
continue
|
||||
}
|
||||
if voucherPriceRule.Type != TypeVoucher {
|
||||
continue // bonus vouchers are handled later in separate step
|
||||
}
|
||||
if !voucherPriceRule.CumulateWithOtherVouchers {
|
||||
continue
|
||||
}
|
||||
|
||||
//check if rule is valid
|
||||
if time.Now().Before(voucherPriceRule.ValidFrom) || time.Now().After(voucherPriceRule.ValidTo) {
|
||||
log.Println("skipping vocucher" + voucherCode + " VlidFrom/ValidTo mismatch")
|
||||
continue
|
||||
}
|
||||
|
||||
//filter out the vouchers that can not be applied due to a mismatch with checkoutAttributes
|
||||
if len(voucherPriceRule.CheckoutAttributes) > 0 {
|
||||
match := false
|
||||
for _, checkoutAttribute := range checkoutAttributes {
|
||||
if contains(checkoutAttribute, voucherPriceRule.CheckoutAttributes) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !match {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if !voucherVo.TimeRedeemed.IsZero() {
|
||||
if Verbose {
|
||||
log.Println("voucher " + voucherCode + " already redeemed ... skipping")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
pair := RuleVoucherPair{
|
||||
Rule: voucherPriceRule,
|
||||
Voucher: voucherVo,
|
||||
}
|
||||
ruleVoucherPairsStep21 = append(ruleVoucherPairsStep21, pair)
|
||||
}
|
||||
}
|
||||
//apply them
|
||||
sort.Sort(ByPriority(ruleVoucherPairsStep21))
|
||||
for _, priceRulePair := range ruleVoucherPairsStep21 {
|
||||
orderDiscounts = calculateRule(orderDiscounts, priceRulePair, calculationParameters)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
// shipping - step 3
|
||||
// shipping costs handling
|
||||
@ -335,61 +434,57 @@ func ApplyDiscounts(articleCollection *ArticleCollection, existingDiscounts Orde
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
// vouchers: step 5
|
||||
// bonus vouchers: step 5
|
||||
// find the vouchers and voucher rules
|
||||
// find applicable pricerules of type TypeVoucher for
|
||||
|
||||
if len(bonusVoucherCodes) > 0 {
|
||||
var ruleVoucherPairsStep5 []RuleVoucherPair
|
||||
for _, voucherCode := range bonusVoucherCodes {
|
||||
if len(voucherCode) > 0 {
|
||||
voucherVo, voucherPriceRule, err := GetVoucherAndPriceRule(voucherCode, customProvider)
|
||||
if voucherVo == nil {
|
||||
log.Println("voucher not found for code: " + voucherCode + " in " + "priceRule.ApplyDiscounts")
|
||||
}
|
||||
if err != nil {
|
||||
log.Println("skipping voucher "+voucherCode, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if voucherPriceRule.Type != TypeBonusVoucher {
|
||||
log.Println("skipping voucher "+voucherCode+" with type BonusVoucher", err)
|
||||
continue
|
||||
}
|
||||
|
||||
//check if rule is valid
|
||||
if time.Now().Before(voucherPriceRule.ValidFrom) || time.Now().After(voucherPriceRule.ValidTo) {
|
||||
log.Println("skipping vocucher" + voucherCode + " VlidFrom/ValidTo mismatch")
|
||||
continue
|
||||
}
|
||||
|
||||
if !voucherVo.TimeRedeemed.IsZero() {
|
||||
if Verbose {
|
||||
log.Println("voucher " + voucherCode + " already redeemed ... skipping")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
pair := RuleVoucherPair{
|
||||
Rule: voucherPriceRule,
|
||||
Voucher: voucherVo,
|
||||
}
|
||||
ruleVoucherPairsStep5 = append(ruleVoucherPairsStep5, pair)
|
||||
var ruleVoucherPairsStep5 []RuleVoucherPair
|
||||
for _, voucherCode := range voucherCodes {
|
||||
if len(voucherCode) > 0 {
|
||||
voucherVo, voucherPriceRule, err := GetVoucherAndPriceRule(voucherCode, customProvider)
|
||||
if voucherVo == nil {
|
||||
//log.Println("voucher not found for code: " + voucherCode + " in " + "priceRule.ApplyDiscounts")
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
log.Println("skipping voucher "+voucherCode, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if voucherPriceRule.Type != TypeBonusVoucher {
|
||||
continue
|
||||
}
|
||||
|
||||
//check if rule is valid
|
||||
if time.Now().Before(voucherPriceRule.ValidFrom) || time.Now().After(voucherPriceRule.ValidTo) {
|
||||
log.Println("skipping vocucher" + voucherCode + " VlidFrom/ValidTo mismatch")
|
||||
continue
|
||||
}
|
||||
|
||||
if !voucherVo.TimeRedeemed.IsZero() {
|
||||
if Verbose {
|
||||
log.Println("voucher " + voucherCode + " already redeemed ... skipping")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
pair := RuleVoucherPair{
|
||||
Rule: voucherPriceRule,
|
||||
Voucher: voucherVo,
|
||||
}
|
||||
ruleVoucherPairsStep5 = append(ruleVoucherPairsStep5, pair)
|
||||
}
|
||||
//apply them
|
||||
}
|
||||
//apply them
|
||||
|
||||
//no products should be blacklisted
|
||||
calculationParameters.blacklistedItemIDs = []string{}
|
||||
//no products should be blacklisted
|
||||
calculationParameters.blacklistedItemIDs = []string{}
|
||||
|
||||
// the bonus voucher should be applicable on shipping costs as well
|
||||
calculationParameters.shippingGroupIDs = []string{}
|
||||
// the bonus voucher should be applicable on shipping costs as well
|
||||
calculationParameters.shippingGroupIDs = []string{}
|
||||
|
||||
for _, priceRulePair := range ruleVoucherPairsStep5 {
|
||||
orderDiscounts = calculateRule(orderDiscounts, priceRulePair, calculationParameters)
|
||||
}
|
||||
for _, priceRulePair := range ruleVoucherPairsStep5 {
|
||||
orderDiscounts = calculateRule(orderDiscounts, priceRulePair, calculationParameters)
|
||||
}
|
||||
|
||||
timeTrack(nowAll, "All rules together")
|
||||
@ -720,9 +815,17 @@ func validatePriceRule(priceRule PriceRule, checkedPosition *Article, calculatio
|
||||
if !checkedPosition.AllowCrossPriceCalculation {
|
||||
return false, ValidationVoucherNotApplicableToAlreadyDiscountedItemsBySap
|
||||
}
|
||||
|
||||
// Check if there is already any webshop promo discount
|
||||
discounts, ok := orderDiscounts[checkedPosition.ID]
|
||||
if ok && len(discounts.AppliedDiscounts) > 0 {
|
||||
// filter all employee discounts, these are an exception for flag ExcludeAlreadyDiscountedItemsForVoucher
|
||||
filteredDiscounts := filterDiscounts(discounts.AppliedDiscounts, func(d DiscountApplied) bool {
|
||||
if !d.IsTypePromotionCustomer {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
if ok && len(filteredDiscounts) > 0 {
|
||||
return false, ValidationVoucherNotApplicableToAlreadyDiscountedItemsByWebshop
|
||||
}
|
||||
}
|
||||
@ -1002,3 +1105,13 @@ func getShippingGroupIDs() (itemIDs []string, err error) {
|
||||
itemIDs = RemoveDuplicates(itemIDs)
|
||||
return
|
||||
}
|
||||
|
||||
func filterDiscounts(discounts []DiscountApplied, f func(DiscountApplied) bool) []DiscountApplied {
|
||||
filtered := []DiscountApplied{}
|
||||
for _, discount := range discounts {
|
||||
if f(discount) {
|
||||
filtered = append(filtered, discount)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
@ -60,14 +60,8 @@ func LoadGroup(ID string, customProvider PriceRuleCustomProvider) (*Group, error
|
||||
return GetGroupByID(ID, customProvider)
|
||||
}
|
||||
|
||||
// RemoveAllProductIds - clear all product IDs
|
||||
func (group *Group) RemoveAllProductIds() bool {
|
||||
group.ItemIDs = []string{}
|
||||
return true
|
||||
}
|
||||
|
||||
// AddGroupItemIDsAndPersist - appends removes duplicates and persists
|
||||
func (group *Group) AddGroupItemIDsAndPersist(itemIDs []string) bool {
|
||||
func (group *Group) AddGroupItemIDsAndPersist(itemIDs []string) error {
|
||||
group.AddGroupItemIDs(itemIDs)
|
||||
|
||||
//addtoset
|
||||
@ -76,17 +70,17 @@ func (group *Group) AddGroupItemIDsAndPersist(itemIDs []string) bool {
|
||||
|
||||
_, err := collection.Upsert(bson.M{"id": group.ID}, group)
|
||||
if err != nil {
|
||||
return false
|
||||
return err
|
||||
}
|
||||
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddGroupItemIDs - appends removes duplicates and persists
|
||||
func (group *Group) AddGroupItemIDs(itemIDs []string) bool {
|
||||
func (group *Group) AddGroupItemIDs(itemIDs []string) {
|
||||
var ids = append(group.ItemIDs, itemIDs...)
|
||||
group.ItemIDs = RemoveDuplicates(ids)
|
||||
return true
|
||||
return
|
||||
}
|
||||
|
||||
// GroupAlreadyExistsInDB checks if a Group with given ID already exists in the database
|
||||
|
||||
@ -129,11 +129,16 @@ type PriceRule struct {
|
||||
|
||||
Custom interface{} `bson:",omitempty"` //make it extensible if needed (included, excluded group IDs)
|
||||
|
||||
ExcludeAlreadyDiscountedItemsForVoucher bool
|
||||
// if true, voucher is not applied when item already has a discount (SAP or webshop pricerule)
|
||||
// exception: employee discount is always granted when available
|
||||
ExcludeAlreadyDiscountedItemsForVoucher bool // flag for vouchers only.
|
||||
|
||||
ExcludesEmployeesForVoucher bool // Note: exclusion of employees must actually be configured by setting IncludedCustomerGroupIDS/ExcludedCustomerGroupIDS.
|
||||
// Note: exclusion of employees must actually be configured by setting IncludedCustomerGroupIDS/ExcludedCustomerGroupIDS.
|
||||
// This flag is used for external validation purposes and only provides the information that this promo is supposed to exclude employees.
|
||||
// It has no effect on the promo calculation itself!
|
||||
ExcludesEmployeesForVoucher bool // flag for vouchers only
|
||||
|
||||
CumulateWithOtherVouchers bool // flag for vouchers only. If true, voucher will be applied on top of other vouchers (best option rule skipped)
|
||||
}
|
||||
|
||||
//Type the type of the price rule
|
||||
|
||||
654
pricerule/pricerule_cumulation_test.go
Normal file
654
pricerule/pricerule_cumulation_test.go
Normal file
@ -0,0 +1,654 @@
|
||||
package pricerule
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/foomo/shop/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCumulationTwoVouchers_OnePerSku(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Expected result: one of the vouchers is applied to each item
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-sku1", 10.0, []string{helper.GroupIDSingleSku1}, false, false)
|
||||
voucherCode2 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-sku2", 10.0, []string{helper.GroupIDSingleSku2}, false, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 10% on 30 CHF
|
||||
assert.Equal(t, 3.0, summary.TotalDiscountApplicable)
|
||||
}
|
||||
func TestCumulationTwoVouchers_BothForSameSku(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Both voucher are only valid for one of the items
|
||||
// Expected result: One voucher is being applied, the other one is dismissed
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-sku1", 10.0, []string{helper.GroupIDSingleSku1}, false, false)
|
||||
voucherCode2 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-sku2", 10.0, []string{helper.GroupIDSingleSku1}, false, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// only one voucher should be applied => 1 CHF
|
||||
assert.Equal(t, 1.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationTwoVouchers_BothForBothSkus(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Both voucher are valid for both of the items
|
||||
// Expected result: The better voucher is applied to both items
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-1", 5.0, []string{helper.GroupIDTwoSkus}, false, false)
|
||||
voucherCode2 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-2", 10.0, []string{helper.GroupIDTwoSkus}, false, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 10% on 30 CHF
|
||||
assert.Equal(t, 3.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationTwoVouchers_BothForSameSku_AdditonalCrossPrice(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Both voucher are only valid for one of the items
|
||||
// Expected result: - both items discounted by product promo
|
||||
// - One voucher is being applied, the other one is dismissed
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
helper.setMockPriceRuleCrossPrice(t, "crossprice1", 5.0, false, []string{helper.GroupIDTwoSkus})
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-sku1", 5.0, []string{helper.GroupIDSingleSku1}, false, false)
|
||||
voucherCode2 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-sku2", 10.0, []string{helper.GroupIDSingleSku1}, false, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// helper.Sku1: 5 + 0.5, helper.Sku2: 5 => 10.5
|
||||
assert.Equal(t, 10.5, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationProductPromo(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Expected result: - only better cross price should be applied
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
helper.setMockPriceRuleCrossPrice(t, "crossprice1", 2.0, false, []string{helper.GroupIDTwoSkus})
|
||||
helper.setMockPriceRuleCrossPrice(t, "crossprice2", 5.0, false, []string{helper.GroupIDTwoSkus})
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{}, []string{}, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 5+5 (5 on each product) = 10 CHF
|
||||
assert.Equal(t, 10.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
|
||||
func TestCumulationForExcludeVoucherOnCrossPriceWebhop(t *testing.T) {
|
||||
// Cart with 2 Items
|
||||
// Expected result: voucher is only applied to sku2. helper.Sku1 is skipped due to existing webshop cross-price
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
helper.setMockPriceRuleCrossPrice(t, "crossprice1", 5.0, false, []string{helper.GroupIDSingleSku1})
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-1", 10.0, []string{helper.GroupIDTwoSkus}, true, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// helper.Sku1: 5, helper.Sku2: 2
|
||||
assert.Equal(t, 7.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationForExcludeVoucherOnCrossPriceSAP(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Expected result: voucher is only applied to sku2. helper.Sku1 is skipped due to existing SAP cross-price
|
||||
// (indicated by AllowCrossPriceCalculation == false)
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
for i, article := range articleCollection.Articles {
|
||||
if i == 0 {
|
||||
article.AllowCrossPriceCalculation = false // this is false if there already is a SAP crossprice
|
||||
}
|
||||
}
|
||||
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-1", 10.0, []string{helper.GroupIDTwoSkus}, true, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// helper.Sku2: 2 CHF
|
||||
assert.Equal(t, 2.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
|
||||
func TestCumulationTwoVouchers_BothForBothSkus_BothApplied(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items (CHF 20 and CHF 10)
|
||||
// Both voucher are valid for both of the items
|
||||
// Expected result: Both voucher are applied because on voucher has set CumulateWithOtherVouchers = true
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1, _ := helper.setMockPriceRuleAndVoucherAbsoluteCHF20(t, true)
|
||||
voucherCode2 := helper.setMockPriceRuleAndVoucher10Percent(t, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 20 CHF (absolute) + 3 (10%) = 23
|
||||
assert.Equal(t, 23.0, summary.TotalDiscountApplicable)
|
||||
}
|
||||
func TestCumulationTwoVouchers_BothForBothSkus_SamePromo_BothApplied(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items (CHF 20 and CHF 10)
|
||||
// Both voucher are valid for both of the items
|
||||
// Vouchers are of same promo
|
||||
// CumulateWithOtherVouchers = true
|
||||
// Expected result: Both voucher are applied because CumulateWithOtherVouchers = true
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1, voucherCode2 := helper.setMockPriceRuleAndVoucherAbsoluteCHF20(t, true)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 20 CHF (absolute) + 10 (20 CHF but only 10 applicable) = 30
|
||||
assert.Equal(t, 30.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationTwoVouchers_BothForBothSkus_SamePromoOnlyOneApplied(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items (CHF 20 and CHF 10)
|
||||
// Both voucher are valid for both of the items
|
||||
// Vouchers are of same promo
|
||||
// CumulateWithOtherVouchers = false
|
||||
// Expected result: Only one voucher is applied because CumulateWithOtherVouchers = true
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1, voucherCode2 := helper.setMockPriceRuleAndVoucherAbsoluteCHF20(t, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 20 CHF (absolute) 0 = 20
|
||||
assert.Equal(t, 20.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationBonusVoucher(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items (CHF 20 and CHF 10)
|
||||
// Both bonus vouchers should be applied
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupTestData(t)
|
||||
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1, voucherCode2 := helper.setMockBonusVoucherPriceRule(t)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 10 +10 = 20 CHF
|
||||
assert.Equal(t, 20.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
|
||||
func TestCumulationExcludeEmployeesFromVoucher(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Expected result: only regular customer gets discount
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-sku1", 10.0, []string{helper.GroupIDTwoSkus}, false, true)
|
||||
|
||||
// Get Discounts for regular customer
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 10% on 30 CHF
|
||||
assert.Equal(t, 3.0, summary.TotalDiscountApplicable)
|
||||
|
||||
// Change customer type to employee => no discount
|
||||
articleCollection.CustomerType = helper.CustomerGroupEmployee
|
||||
discounts, summary, errApply = ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// No discount for employee
|
||||
assert.Equal(t, 0.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationEmployeeDiscount(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Expected result: only employee customer gets discount
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
helper.setMockEmployeeDiscount10Percent(t, "employee-discount", []string{helper.GroupIDTwoSkus})
|
||||
|
||||
// no employee discuonts for regular customer
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
assert.Equal(t, 0.0, summary.TotalDiscountApplicable)
|
||||
|
||||
// Change customer type to eomplyee => discount applied
|
||||
articleCollection.CustomerType = helper.CustomerGroupEmployee
|
||||
discounts, summary, errApply = ApplyDiscounts(articleCollection, nil, []string{}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// No discount for non-regular customer
|
||||
assert.Equal(t, 3.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationCrossPriceAndEmployeeDiscount(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Expected result: regular customer gets crossprice, employee gets additional employee discount
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
helper.setMockPriceRuleCrossPrice(t, "cross-price", 5.0, false, []string{helper.GroupIDTwoSkus})
|
||||
helper.setMockEmployeeDiscount10Percent(t, "employee-discount", []string{helper.GroupIDTwoSkus})
|
||||
|
||||
// no employee discounts for regular customer
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 5+5 CHF Crossprices, no employee discount
|
||||
assert.Equal(t, 10.0, summary.TotalDiscountApplicable)
|
||||
|
||||
// Change customer type to eomplyee => discount applied
|
||||
articleCollection.CustomerType = helper.CustomerGroupEmployee
|
||||
discounts, summary, errApply = ApplyDiscounts(articleCollection, nil, []string{}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 5+5 CHF Crossprices + 2 CHF employee discount
|
||||
assert.Equal(t, 12.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationEmployeeDiscountAndVoucherIncluceDiscountedItems(t *testing.T) {
|
||||
|
||||
// - Cart with 2 Items
|
||||
// - Cross-price on Sku1
|
||||
// - Employee discount on both items
|
||||
// - 10% Voucher
|
||||
// Expected result: Employee discount is granted regardless of flag ExcludeAlreadyDiscountedItemsForVoucher
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
helper.setMockPriceRuleCrossPrice(t, "cross-price", 5.0, false, []string{helper.GroupIDSingleSku1})
|
||||
helper.setMockEmployeeDiscount10Percent(t, "employee-discount", []string{helper.GroupIDTwoSkus})
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-sku1", 10.0, []string{helper.GroupIDTwoSkus}, false, false)
|
||||
// no employee discounts for regular customer
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
// 5 CHF crossprice for Sku1 + 2.5 CHF voucher discount
|
||||
assert.Equal(t, 7.5, summary.TotalDiscountApplicable)
|
||||
|
||||
// Change customer type to employee => additional employee discount
|
||||
articleCollection.CustomerType = helper.CustomerGroupEmployee
|
||||
discounts, summary, errApply = ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
// 5 CHF crossprice for Sku1 + 2.5 CHF employee discount + 2.25 CHF voucher discount
|
||||
assert.Equal(t, 9.75, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationEmployeeDiscountAndVoucherExcludeDiscountedItems(t *testing.T) {
|
||||
|
||||
// - Cart with 2 Items
|
||||
// - Cross-price on Sku1
|
||||
// - Employee discount on both items
|
||||
// - 10% Voucher
|
||||
// Expected result: Employee discount is granted regardless of flag ExcludeAlreadyDiscountedItemsForVoucher
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
helper.setMockPriceRuleCrossPrice(t, "cross-price", 5.0, false, []string{helper.GroupIDSingleSku1})
|
||||
helper.setMockEmployeeDiscount10Percent(t, "employee-discount", []string{helper.GroupIDTwoSkus})
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-sku1", 10.0, []string{helper.GroupIDTwoSkus}, true, false)
|
||||
|
||||
// no employee discounts for regular customer
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
// 5 CHF crossprice for Sku1 + 2 CHF voucher discount
|
||||
assert.Equal(t, 7.0, summary.TotalDiscountApplicable)
|
||||
|
||||
// Change customer type to employee => additional employee discount
|
||||
articleCollection.CustomerType = helper.CustomerGroupEmployee
|
||||
discounts, summary, errApply = ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
// 5 CHF crossprice for Sku1 + 0.5+2.0 employee discount + 1.8 CHF voucher discount (for Sku2)
|
||||
assert.Equal(t, 9.3, summary.TotalDiscountApplicable)
|
||||
}
|
||||
func TestCumulationEmployeeDiscountAndVoucherExcludeDiscountedItemsSAPCrossPrice(t *testing.T) {
|
||||
|
||||
// Same as TestCumulationEmployeeDiscountAndVoucherExcludeDiscountedItems but with SAP cross-price instead of webshop cross-price
|
||||
|
||||
// - Cart with 2 Items
|
||||
// - Cross-price on Sku1
|
||||
// - Employee discount on both items
|
||||
// - 10% Voucher
|
||||
// Expected result: Employee discount is granted regardless of flag ExcludeAlreadyDiscountedItemsForVoucher
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
// Simulate SAP cross price
|
||||
articleCollection.Articles[0].Price = 5.0
|
||||
articleCollection.Articles[0].AllowCrossPriceCalculation = false
|
||||
|
||||
helper.setMockEmployeeDiscount10Percent(t, "employee-discount", []string{helper.GroupIDTwoSkus})
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucherXPercent(t, "voucher-sku1", 10.0, []string{helper.GroupIDTwoSkus}, true, false)
|
||||
|
||||
// no employee discounts for regular customer
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
// 2 CHF voucher discount (Sku2)
|
||||
assert.Equal(t, 2.0, summary.TotalDiscountApplicable)
|
||||
|
||||
// Change customer type to employee => additional employee discount
|
||||
articleCollection.CustomerType = helper.CustomerGroupEmployee
|
||||
discounts, summary, errApply = ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.NoError(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
// 0.5+2.0 employee discount + 1.8 CHF voucher discount (for Sku2)
|
||||
assert.Equal(t, 4.3, summary.TotalDiscountApplicable)
|
||||
}
|
||||
|
||||
func TestCrossPriceAndBuyXGetY(t *testing.T) {
|
||||
|
||||
// Expected: Crossprice and BuyXPayY are both applied
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
allowCrossPriceCalculation := true
|
||||
// add 3rd article required for BuyXPayY Promo
|
||||
articleCollection.Articles = append(articleCollection.Articles, &Article{
|
||||
ID: helper.Sku3,
|
||||
Price: 50.0,
|
||||
CrossPrice: 50.0,
|
||||
Quantity: 1,
|
||||
AllowCrossPriceCalculation: allowCrossPriceCalculation,
|
||||
})
|
||||
// adjuts prices
|
||||
articleCollection.Articles[0].Price = 100.0
|
||||
articleCollection.Articles[1].Price = 50.0
|
||||
|
||||
helper.setMockPriceRuleCrossPrice(t, "crossprice1", 10.0, false, []string{helper.GroupIDThreeSkus})
|
||||
helper.setMockPriceRuleBuy3Pay2(t, "buyXPayY", []string{helper.GroupIDThreeSkus})
|
||||
|
||||
tests := []struct {
|
||||
qty1 float64
|
||||
qty2 float64
|
||||
qty3 float64
|
||||
expectedDiscountOrderService float64
|
||||
expectedDiscountCatalogue float64
|
||||
}{
|
||||
{1.0, 1.0, 1.0, 70.0, 30.0}, // 10+10+10+10+40=70
|
||||
{2.0, 1.0, 1.0, 80.0, 40.0},
|
||||
{2.0, 2.0, 2.0, 140.0, 60.0}, // 2 items free
|
||||
{2.0, 1.0, 0.0, 70.0, 30.0},
|
||||
{0.0, 1.0, 1.0, 20.0, 20.0}, // only cross prices
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
// Order -------------------------------------------------------------------------------
|
||||
articleCollection.Articles[0].Quantity = tt.qty1
|
||||
articleCollection.Articles[1].Quantity = tt.qty2
|
||||
articleCollection.Articles[2].Quantity = tt.qty3
|
||||
|
||||
// Calculation for orderservice
|
||||
_, summary, err := ApplyDiscounts(articleCollection, nil, []string{""}, []string{}, 0.05, nil)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, tt.expectedDiscountOrderService, summary.TotalDiscount, "case orderservice", i)
|
||||
|
||||
// Calculation for catalogue
|
||||
discountsCatalogue, _, err := ApplyDiscountsOnCatalog(articleCollection, nil, 0.05, nil)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
// Note: In catalalogue calculation summary is always empty, therefore we have to get the data directly from the discounts
|
||||
assert.Equal(t, tt.expectedDiscountCatalogue, helper.accumulateDiscountsOfItems(discountsCatalogue), "case catalogue", i)
|
||||
}
|
||||
}
|
||||
func TestCrossPriceAndEmployeeDiscount(t *testing.T) {
|
||||
|
||||
// Expected: Crossprice and BuyXPayY are both applied
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
articleCollection.CustomerType = helper.CustomerGroupEmployee
|
||||
|
||||
includedProdcuts := []string{helper.GroupIDTwoSkus}
|
||||
helper.setMockEmployeeDiscount10Percent(t, "employee-discount", includedProdcuts)
|
||||
|
||||
tests := []struct {
|
||||
customerType string
|
||||
amountCrossPrice float64
|
||||
isCrosspricePercent bool
|
||||
expectedDiscountOrderService float64
|
||||
expectedDiscountCatalogue float64
|
||||
}{
|
||||
{helper.CustomerGroupRegular, 5.0, false, 10.0, 10.0},
|
||||
{helper.CustomerGroupRegular, 10.0, true, 3.0, 3.0},
|
||||
{helper.CustomerGroupEmployee, 5.0, false, 12.0, 10.0},
|
||||
{helper.CustomerGroupEmployee, 10.0, true, 5.7, 3.0}, //@todo actual caculated result is 5.699999999999999 => fix rounding errors
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
articleCollection.CustomerType = tt.customerType
|
||||
helper.setMockPriceRuleCrossPrice(t, "crossprice1", tt.amountCrossPrice, tt.isCrosspricePercent, includedProdcuts)
|
||||
// Calculation for orderservice
|
||||
_, summary, err := ApplyDiscounts(articleCollection, nil, []string{""}, []string{}, 0.05, nil)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.expectedDiscountOrderService, utils.Round(summary.TotalDiscount, 2), "case orderservice", i)
|
||||
|
||||
// Calculation for catalogue
|
||||
discountsCatalogue, _, err := ApplyDiscountsOnCatalog(articleCollection, nil, 0.05, nil)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
// Note: In catalalogue calculation summary is always empty, therefore we have to get the data directly from the discounts
|
||||
assert.Equal(t, tt.expectedDiscountCatalogue, helper.accumulateDiscountsOfItems(discountsCatalogue), "case catalogue", i)
|
||||
}
|
||||
}
|
||||
func TestQuantityThreshold(t *testing.T) {
|
||||
|
||||
// Expected: Discount is applied if qty of one item is at least equal to threshold
|
||||
// Note: if threshold is met for ONE item, discount will be applied to ALL products eligible for this promo
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
tests := []struct {
|
||||
includedProducts []string
|
||||
amount float64
|
||||
threshold float64
|
||||
qty1 float64
|
||||
qty2 float64
|
||||
expectedDiscount float64
|
||||
}{
|
||||
{[]string{helper.GroupIDTwoSkus}, 1.0, 3.0, 1.0, 1.0, 0.0},
|
||||
{[]string{helper.GroupIDTwoSkus}, 1.0, 2.0, 1.0, 1.0, 2.0},
|
||||
{[]string{helper.GroupIDTwoSkus}, 1.0, 2.0, 2.0, 1.0, 3.0},
|
||||
{[]string{helper.GroupIDTwoSkus}, 1.0, 2.0, 2.0, 0.0, 2.0},
|
||||
{[]string{helper.GroupIDTwoSkus}, 1.0, 2.0, 2.0, 2.0, 4.0},
|
||||
{[]string{helper.GroupIDSingleSku1}, 1.0, 2.0, 2.0, 2.0, 2.0},
|
||||
{[]string{helper.GroupIDSingleSku1}, 1.0, 2.0, 1.0, 1.0, 0.0},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
articleCollection.Articles[0].Quantity = tt.qty1
|
||||
articleCollection.Articles[1].Quantity = tt.qty2
|
||||
helper.setMockPriceRuleQtyThreshold(t, "qty-threshold", tt.amount, tt.threshold, tt.includedProducts)
|
||||
|
||||
_, summary, err := ApplyDiscounts(articleCollection, nil, []string{""}, []string{}, 0.05, nil)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.expectedDiscount, summary.TotalDiscount, "case ", i)
|
||||
|
||||
}
|
||||
}
|
||||
func TestThresholdAmount(t *testing.T) {
|
||||
|
||||
// Expected: Discount is applied if threshold amount is met by all eligible items
|
||||
|
||||
helper := newTesthelper()
|
||||
defer helper.cleanupTestData(t)
|
||||
helper.cleanupAndRecreateTestData(t)
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
tests := []struct {
|
||||
includedProducts []string
|
||||
thresholdAmount float64
|
||||
qty1 float64
|
||||
qty2 float64
|
||||
expectedDiscount float64
|
||||
}{
|
||||
{[]string{helper.GroupIDTwoSkus}, 30.0, 1.0, 1.0, 10.0},
|
||||
{[]string{helper.GroupIDTwoSkus}, 40.0, 1.0, 1.0, 0.0},
|
||||
{[]string{helper.GroupIDTwoSkus}, 30.0, 0.0, 2.0, 10.0},
|
||||
{[]string{helper.GroupIDTwoSkus}, 30.0, 1.0, 1.0, 10.0},
|
||||
{[]string{helper.GroupIDTwoSkus}, 40.0, 1.0, 1.0, 0.0},
|
||||
{[]string{helper.GroupIDTwoSkus}, 30.0, 0.0, 2.0, 10.0},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
articleCollection.Articles[0].Quantity = tt.qty1
|
||||
articleCollection.Articles[1].Quantity = tt.qty2
|
||||
helper.setMockPriceRuleThresholdAmount(t, "qty-threshold", 5.0, tt.thresholdAmount, tt.includedProducts)
|
||||
|
||||
_, summary, err := ApplyDiscounts(articleCollection, nil, []string{""}, []string{}, 0.05, nil)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.expectedDiscount, summary.TotalDiscount, "case ", i)
|
||||
|
||||
}
|
||||
}
|
||||
@ -64,89 +64,12 @@ const (
|
||||
CustomerID1 = "CustomerID1"
|
||||
CustomerID2 = "CustomerID2"
|
||||
|
||||
CustomerGroupID1 = "CustomerGroupID1 - super customer"
|
||||
CustomerGroupID2 = "CustomerGroupID2 - employee"
|
||||
CustomerGroupRegular = "regular-customer"
|
||||
CustomerGroupEmployee = "employee"
|
||||
)
|
||||
|
||||
var productsInGroups map[string][]string
|
||||
|
||||
func Init(t *testing.T) {
|
||||
|
||||
productsInGroups = make(map[string][]string)
|
||||
productsInGroups[GroupIDSingleSku1] = []string{Sku1}
|
||||
productsInGroups[GroupIDSingleSku2] = []string{Sku2}
|
||||
productsInGroups[GroupIDTwoSkus] = []string{Sku1, Sku2}
|
||||
productsInGroups[GroupIDSale] = []string{ProductID1, ProductID2, ProductID1SKU1, ProductID1SKU2, ProductID2SKU1, ProductID2SKU2}
|
||||
productsInGroups[GroupIDNormal] = []string{ProductID4, ProductID5, ProductID4SKU1, ProductID4SKU2, ProductID5SKU1, ProductID5SKU2}
|
||||
productsInGroups[GroupIDShirts] = []string{ProductID3, ProductID4, ProductID5, ProductID3SKU1, ProductID4SKU1, ProductID5SKU1, ProductID3SKU2, ProductID4SKU2, ProductID5SKU2}
|
||||
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
checkGroupsNotExists(t)
|
||||
createMockCustomerGroups(t)
|
||||
createMockProductGroups(t)
|
||||
checkGroupsExists(t)
|
||||
|
||||
createMockPriceRules(t)
|
||||
checkPriceRulesExists(t)
|
||||
|
||||
createMockVouchers(t)
|
||||
checkVouchersExists(t)
|
||||
}
|
||||
|
||||
func TestBuyXPayY(t *testing.T) {
|
||||
//remove all and add again
|
||||
productsInGroups = make(map[string][]string)
|
||||
productsInGroups[GroupIDSale] = []string{ProductID1, ProductID2, ProductID1SKU1, ProductID1SKU2, ProductID2SKU1, ProductID2SKU2}
|
||||
productsInGroups[GroupIDNormal] = []string{ProductID4, ProductID5, ProductID4SKU1, ProductID4SKU2, ProductID5SKU1, ProductID5SKU2}
|
||||
productsInGroups[GroupIDShirts] = []string{ProductID3, ProductID4, ProductID5, ProductID3SKU1, ProductID4SKU1, ProductID5SKU1, ProductID3SKU2, ProductID4SKU2, ProductID5SKU2}
|
||||
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
checkGroupsNotExists(t)
|
||||
createMockCustomerGroups(t)
|
||||
createMockProductGroups(t)
|
||||
checkGroupsExists(t)
|
||||
|
||||
orderVo := &ArticleCollection{}
|
||||
|
||||
orderVo.CustomerID = CustomerID1
|
||||
orderVo.CustomerType = CustomerID1
|
||||
|
||||
// Position with 2 qnt
|
||||
positionVo := &Article{}
|
||||
positionVo.ID = ProductID1
|
||||
positionVo.Price = 10
|
||||
positionVo.Quantity = 3
|
||||
orderVo.Articles = append(orderVo.Articles, positionVo)
|
||||
|
||||
priceRule := NewPriceRule(PriceRuleIDSaleVoucher)
|
||||
priceRule.Name = map[string]string{
|
||||
"de": PriceRuleIDSaleVoucher,
|
||||
"fr": PriceRuleIDSaleVoucher,
|
||||
"it": PriceRuleIDSaleVoucher,
|
||||
}
|
||||
priceRule.Type = TypePromotionProduct
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionBuyXPayY
|
||||
priceRule.Amount = 20.0
|
||||
priceRule.X = 3
|
||||
priceRule.Y = 2
|
||||
priceRule.IncludedProductGroupIDS = []string{GroupIDSale}
|
||||
err := priceRule.Upsert()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
discountsVo, summary, err := ApplyDiscounts(orderVo, nil, []string{}, []string{}, 0.05, nil)
|
||||
utils.PrintJSON(discountsVo)
|
||||
utils.PrintJSON(summary)
|
||||
utils.PrintJSON(err)
|
||||
|
||||
}
|
||||
|
||||
func TestQntThreshold(t *testing.T) {
|
||||
//remove all and add again
|
||||
productsInGroups = make(map[string][]string)
|
||||
@ -158,7 +81,7 @@ func TestQntThreshold(t *testing.T) {
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
checkGroupsNotExists(t)
|
||||
createMockCustomerGroups(t)
|
||||
|
||||
createMockProductGroups(t)
|
||||
checkGroupsExists(t)
|
||||
|
||||
@ -198,7 +121,8 @@ func TestQntThreshold(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testBonuVoucher(t *testing.T) {
|
||||
func TestBonuVoucher(t *testing.T) {
|
||||
|
||||
productsInGroups = make(map[string][]string)
|
||||
productsInGroups[GroupIDSale] = []string{ProductID1, ProductID2, ProductID1SKU1, ProductID1SKU2, ProductID2SKU1, ProductID2SKU2}
|
||||
productsInGroups[GroupIDNormal] = []string{ProductID4, ProductID5, ProductID4SKU1, ProductID4SKU2, ProductID5SKU1, ProductID5SKU2}
|
||||
@ -284,7 +208,8 @@ func testBonuVoucher(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test groups creation
|
||||
func testGetApplicableVouchers(t *testing.T) {
|
||||
func TestGetApplicableVouchers(t *testing.T) {
|
||||
|
||||
//remove all and add again
|
||||
productsInGroups = make(map[string][]string)
|
||||
productsInGroups[GroupIDSale] = []string{ProductID1, ProductID2, ProductID1SKU1, ProductID1SKU2, ProductID2SKU1, ProductID2SKU2}
|
||||
@ -295,7 +220,7 @@ func testGetApplicableVouchers(t *testing.T) {
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
checkGroupsNotExists(t)
|
||||
createMockCustomerGroups(t)
|
||||
|
||||
createMockProductGroups(t)
|
||||
checkGroupsExists(t)
|
||||
orderVo, err := createMockOrder(t)
|
||||
@ -316,7 +241,7 @@ func testGetApplicableVouchers(t *testing.T) {
|
||||
priceRule.Amount = 20.0
|
||||
priceRule.Priority = 800
|
||||
priceRule.IncludedProductGroupIDS = []string{GroupIDSale}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupID1}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupRegular}
|
||||
err = priceRule.Upsert()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -370,7 +295,7 @@ func testGetApplicableVouchers(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testShipping1(t *testing.T) {
|
||||
func TestShipping1(t *testing.T) {
|
||||
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
@ -514,7 +439,8 @@ func testShipping1(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testBlacklist(t *testing.T) {
|
||||
func TestBlacklist(t *testing.T) {
|
||||
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
@ -602,7 +528,8 @@ func testBlacklist(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testDiscountDistribution(t *testing.T) {
|
||||
func TestDiscountDistribution(t *testing.T) {
|
||||
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
@ -725,7 +652,8 @@ func testDiscountDistribution(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testBestOption(t *testing.T) {
|
||||
func TestBestOption(t *testing.T) {
|
||||
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
@ -856,7 +784,8 @@ func testBestOption(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testDiscountFoItemSets(t *testing.T) {
|
||||
func TestDiscountFoItemSets(t *testing.T) {
|
||||
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
@ -930,7 +859,8 @@ func testDiscountFoItemSets(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testVoucherRuleWithCheckoutAttributes(t *testing.T) {
|
||||
func TestVoucherRuleWithCheckoutAttributes(t *testing.T) {
|
||||
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
@ -1003,7 +933,7 @@ func testVoucherRuleWithCheckoutAttributes(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testShipping(t *testing.T) {
|
||||
func TestShipping(t *testing.T) {
|
||||
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
@ -1078,8 +1008,7 @@ func testShipping(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testCache(t *testing.T) {
|
||||
Init(t)
|
||||
func TestCache(t *testing.T) {
|
||||
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
@ -1145,10 +1074,8 @@ func testCache(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test groups creation
|
||||
func testScaled(t *testing.T) {
|
||||
//Init
|
||||
func TestScaled(t *testing.T) {
|
||||
|
||||
//Init
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
|
||||
@ -1220,80 +1147,8 @@ func testScaled(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test groups creation
|
||||
func TestBuyXGetY(t *testing.T) {
|
||||
//Init
|
||||
RemoveAllGroups()
|
||||
RemoveAllPriceRules()
|
||||
func TestExclude(t *testing.T) {
|
||||
|
||||
//create group --------------------------------------------------------------------
|
||||
|
||||
groupID := "discounted"
|
||||
group := new(Group)
|
||||
group.Type = ProductGroup
|
||||
group.ID = groupID
|
||||
group.Name = groupID
|
||||
group.AddGroupItemIDs([]string{ProductID1SKU1, ProductID1SKU2, ProductID2SKU1})
|
||||
group.Upsert()
|
||||
|
||||
//create pricerule --------------------------------------------------------------------
|
||||
priceRule := NewPriceRule(PriceRuleIDSale)
|
||||
priceRule.Name = map[string]string{
|
||||
"de": PriceRuleIDSale,
|
||||
"fr": PriceRuleIDSale,
|
||||
"it": PriceRuleIDSale,
|
||||
}
|
||||
priceRule.Type = TypePromotionOrder
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionBuyXPayY
|
||||
priceRule.X = 3
|
||||
priceRule.Y = 1
|
||||
priceRule.WhichXYFree = XYMostExpensiveFree
|
||||
priceRule.WhichXYList = []string{ProductID2SKU1, ProductID1SKU1, ProductID1SKU2}
|
||||
priceRule.MaxUses = 10
|
||||
priceRule.MaxUsesPerCustomer = 10
|
||||
priceRule.IncludedProductGroupIDS = []string{"discounted"}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{}
|
||||
|
||||
err := priceRule.Upsert()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Order -------------------------------------------------------------------------------
|
||||
orderVo := &ArticleCollection{}
|
||||
orderVo.CustomerID = CustomerID1
|
||||
|
||||
positionVo := &Article{}
|
||||
positionVo.ID = ProductID1SKU1
|
||||
positionVo.Price = 100
|
||||
positionVo.Quantity = 2
|
||||
orderVo.Articles = append(orderVo.Articles, positionVo)
|
||||
|
||||
positionVo = &Article{}
|
||||
positionVo.ID = ProductID1SKU2
|
||||
positionVo.Price = 300
|
||||
positionVo.Quantity = float64(2)
|
||||
orderVo.Articles = append(orderVo.Articles, positionVo)
|
||||
|
||||
positionVo = &Article{}
|
||||
positionVo.ID = ProductID2SKU1
|
||||
positionVo.Price = 500
|
||||
positionVo.Quantity = float64(2)
|
||||
orderVo.Articles = append(orderVo.Articles, positionVo)
|
||||
// Order -------------------------------------------------------------------------------
|
||||
discountsVo, summary, err := ApplyDiscounts(orderVo, nil, []string{""}, []string{}, 0.05, nil)
|
||||
// defer removeOrder(orderVo)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println("discounts for buy x get y")
|
||||
utils.PrintJSON(discountsVo)
|
||||
utils.PrintJSON(*summary)
|
||||
|
||||
}
|
||||
|
||||
// Test groups creation
|
||||
func testExclude(t *testing.T) {
|
||||
//remove all and add again
|
||||
productsInGroups = make(map[string][]string)
|
||||
productsInGroups[GroupIDSale] = []string{ProductID1, ProductID2, ProductID1SKU1, ProductID1SKU2, ProductID2SKU1, ProductID2SKU2}
|
||||
@ -1304,7 +1159,7 @@ func testExclude(t *testing.T) {
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
checkGroupsNotExists(t)
|
||||
createMockCustomerGroups(t)
|
||||
|
||||
createMockProductGroups(t)
|
||||
checkGroupsExists(t)
|
||||
orderVo, err := createMockOrder(t)
|
||||
@ -1351,7 +1206,7 @@ func testExclude(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test discounts for customers (employee)
|
||||
func testCustomerDiscounts(t *testing.T) {
|
||||
func TestCustomerDiscounts(t *testing.T) {
|
||||
|
||||
productsInGroups = make(map[string][]string)
|
||||
productsInGroups[GroupIDSale] = []string{ProductID1, ProductID2, ProductID1SKU1, ProductID1SKU2, ProductID2SKU1, ProductID2SKU2}
|
||||
@ -1362,7 +1217,7 @@ func testCustomerDiscounts(t *testing.T) {
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
checkGroupsNotExists(t)
|
||||
createMockCustomerGroups(t)
|
||||
|
||||
createMockProductGroups(t)
|
||||
checkGroupsExists(t)
|
||||
orderVo, err := createMockOrder(t)
|
||||
@ -1425,7 +1280,7 @@ func testCustomerDiscounts(t *testing.T) {
|
||||
priceRule.Amount = 10.0
|
||||
priceRule.Priority = 90
|
||||
priceRule.IncludedProductGroupIDS = []string{GroupIDShirts}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupID1}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupRegular}
|
||||
priceRule.MinOrderAmount = 0
|
||||
priceRule.MinOrderAmountApplicableItemsOnly = true
|
||||
err = priceRule.Upsert()
|
||||
@ -1446,7 +1301,7 @@ func testCustomerDiscounts(t *testing.T) {
|
||||
priceRule.Amount = 10.0
|
||||
priceRule.Priority = 90
|
||||
priceRule.IncludedProductGroupIDS = []string{GroupIDShirts}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupID1}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupRegular}
|
||||
priceRule.MinOrderAmount = 0
|
||||
priceRule.MinOrderAmountApplicableItemsOnly = true
|
||||
err = priceRule.Upsert()
|
||||
@ -1496,7 +1351,8 @@ func testCustomerDiscounts(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testApplicableInCatalogFlag(t *testing.T) {
|
||||
func TestApplicableInCatalogFlag(t *testing.T) {
|
||||
|
||||
productsInGroups = make(map[string][]string)
|
||||
productsInGroups[GroupIDSale] = []string{ProductID1, ProductID2, ProductID1SKU1, ProductID1SKU2, ProductID2SKU1, ProductID2SKU2}
|
||||
productsInGroups[GroupIDNormal] = []string{ProductID4, ProductID5, ProductID4SKU1, ProductID4SKU2, ProductID5SKU1, ProductID5SKU2}
|
||||
@ -1506,7 +1362,7 @@ func testApplicableInCatalogFlag(t *testing.T) {
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
checkGroupsNotExists(t)
|
||||
createMockCustomerGroups(t)
|
||||
|
||||
createMockProductGroups(t)
|
||||
checkGroupsExists(t)
|
||||
orderVo, err := createMockOrder(t)
|
||||
@ -1542,7 +1398,8 @@ func testApplicableInCatalogFlag(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func testAbsoluteVoucher(t *testing.T) {
|
||||
func TestAbsoluteVoucher(t *testing.T) {
|
||||
|
||||
productsInGroups = make(map[string][]string)
|
||||
productsInGroups[GroupIDSale] = []string{ProductID1, ProductID2, ProductID1SKU1, ProductID1SKU2, ProductID2SKU1, ProductID2SKU2}
|
||||
productsInGroups[GroupIDNormal] = []string{ProductID4, ProductID5, ProductID4SKU1, ProductID4SKU2, ProductID5SKU1, ProductID5SKU2}
|
||||
@ -1552,7 +1409,7 @@ func testAbsoluteVoucher(t *testing.T) {
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
checkGroupsNotExists(t)
|
||||
createMockCustomerGroups(t)
|
||||
|
||||
createMockProductGroups(t)
|
||||
checkGroupsExists(t)
|
||||
|
||||
@ -1645,7 +1502,8 @@ func testAbsoluteVoucher(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test groups creation
|
||||
func testMaxOrder(t *testing.T) {
|
||||
func TestMaxOrder(t *testing.T) {
|
||||
|
||||
//remove all and add again
|
||||
productsInGroups = make(map[string][]string)
|
||||
productsInGroups[GroupIDSale] = []string{ProductID1, ProductID2, ProductID1SKU1, ProductID1SKU2, ProductID2SKU1, ProductID2SKU2}
|
||||
@ -1656,7 +1514,7 @@ func testMaxOrder(t *testing.T) {
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
checkGroupsNotExists(t)
|
||||
createMockCustomerGroups(t)
|
||||
|
||||
createMockProductGroups(t)
|
||||
checkGroupsExists(t)
|
||||
orderVo, err := createMockOrder(t)
|
||||
@ -1679,7 +1537,7 @@ func testMaxOrder(t *testing.T) {
|
||||
priceRule.Amount = 10.0
|
||||
priceRule.Priority = 90
|
||||
priceRule.IncludedProductGroupIDS = []string{GroupIDSale}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupID1}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupRegular}
|
||||
priceRule.MinOrderAmount = 0
|
||||
priceRule.MinOrderAmountApplicableItemsOnly = true
|
||||
err = priceRule.Upsert()
|
||||
@ -1743,7 +1601,8 @@ func testMaxOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test groups creation
|
||||
func testTwoStepWorkflow(t *testing.T) {
|
||||
func TestTwoStepWorkflow(t *testing.T) {
|
||||
|
||||
//remove all and add again
|
||||
productsInGroups = make(map[string][]string)
|
||||
productsInGroups[GroupIDSale] = []string{ProductID1, ProductID2, ProductID1SKU1, ProductID1SKU2, ProductID2SKU1, ProductID2SKU2}
|
||||
@ -1754,7 +1613,7 @@ func testTwoStepWorkflow(t *testing.T) {
|
||||
RemoveAllPriceRules()
|
||||
RemoveAllVouchers()
|
||||
checkGroupsNotExists(t)
|
||||
createMockCustomerGroups(t)
|
||||
|
||||
createMockProductGroups(t)
|
||||
checkGroupsExists(t)
|
||||
orderVo, err := createMockOrder(t)
|
||||
@ -1777,7 +1636,7 @@ func testTwoStepWorkflow(t *testing.T) {
|
||||
priceRule.Amount = 10.0
|
||||
priceRule.Priority = 90
|
||||
priceRule.IncludedProductGroupIDS = []string{GroupIDSale}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupID1}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupRegular}
|
||||
err = priceRule.Upsert()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -1795,7 +1654,7 @@ func testTwoStepWorkflow(t *testing.T) {
|
||||
priceRule.Amount = 10.0
|
||||
priceRule.Priority = 100
|
||||
priceRule.IncludedProductGroupIDS = []string{GroupIDSale}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupID1}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupRegular}
|
||||
err = priceRule.Upsert()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -1814,7 +1673,7 @@ func testTwoStepWorkflow(t *testing.T) {
|
||||
priceRule.Amount = 20.0
|
||||
priceRule.Priority = 800
|
||||
priceRule.IncludedProductGroupIDS = []string{GroupIDSale}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupID1}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupRegular}
|
||||
err = priceRule.Upsert()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -1878,9 +1737,8 @@ func testTwoStepWorkflow(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test groups creation
|
||||
func testPricerulesWorkflow(t *testing.T) {
|
||||
func TestPricerulesWorkflow(t *testing.T) {
|
||||
//remove all and add again
|
||||
Init(t)
|
||||
|
||||
orderVo, err := createMockOrder(t)
|
||||
if err != nil {
|
||||
@ -1901,9 +1759,7 @@ func testPricerulesWorkflow(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test checkout functionality
|
||||
func testCheckoutWorkflow(t *testing.T) {
|
||||
//remove all and add again
|
||||
Init(t)
|
||||
func TestCheckoutWorkflow(t *testing.T) {
|
||||
|
||||
orderVo, err := createMockOrder(t)
|
||||
if err != nil {
|
||||
@ -1959,31 +1815,13 @@ func createMockProductGroups(t *testing.T) {
|
||||
group.Type = ProductGroup
|
||||
group.ID = groupID
|
||||
group.Name = groupID
|
||||
group.AddGroupItemIDs(productsInGroups[groupID])
|
||||
err := group.Upsert()
|
||||
err := group.AddGroupItemIDsAndPersist(productsInGroups[groupID])
|
||||
if err != nil {
|
||||
t.Fatal("Could not upsert product group " + groupID)
|
||||
t.Fatal(err, "Could not upsert product group "+groupID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createMockCustomerGroups(t *testing.T) {
|
||||
for _, groupID := range []string{CustomerGroupID1, CustomerGroupID2} {
|
||||
group := new(Group)
|
||||
group.Type = CustomerGroup
|
||||
group.ID = groupID
|
||||
group.Name = groupID
|
||||
group.AddGroupItemIDs([]string{CustomerID1})
|
||||
err := group.Upsert()
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
t.Fatal("Could not upsert customer group " + groupID)
|
||||
}
|
||||
group.AddGroupItemIDsAndPersist([]string{CustomerID2})
|
||||
}
|
||||
}
|
||||
|
||||
// PRICERULES ---------------------------------------------
|
||||
|
||||
func createMockPriceRules(t *testing.T) {
|
||||
@ -2008,7 +1846,7 @@ func createMockPriceRules(t *testing.T) {
|
||||
|
||||
priceRule.IncludedProductGroupIDS = []string{GroupIDSale}
|
||||
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupID1}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupRegular}
|
||||
|
||||
err := priceRule.Upsert()
|
||||
if err != nil {
|
||||
@ -2033,7 +1871,7 @@ func createMockPriceRules(t *testing.T) {
|
||||
|
||||
priceRule.IncludedProductGroupIDS = []string{GroupIDSale}
|
||||
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupID2}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupEmployee}
|
||||
|
||||
err = priceRule.Upsert()
|
||||
if err != nil {
|
||||
|
||||
250
pricerule/pricerule_test_helper.go
Normal file
250
pricerule/pricerule_test_helper.go
Normal file
@ -0,0 +1,250 @@
|
||||
package pricerule
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type cumulationTestHelper struct {
|
||||
CustomerGroupRegular string
|
||||
CustomerGroupEmployee string
|
||||
Sku1 string
|
||||
Sku2 string
|
||||
Sku3 string
|
||||
GroupIDSingleSku1 string
|
||||
GroupIDSingleSku2 string
|
||||
GroupIDTwoSkus string
|
||||
GroupIDThreeSkus string
|
||||
}
|
||||
|
||||
func newTesthelper() cumulationTestHelper {
|
||||
return cumulationTestHelper{
|
||||
CustomerGroupRegular: "customer-regular",
|
||||
CustomerGroupEmployee: "customer-employee",
|
||||
Sku1: "sku1",
|
||||
Sku2: "sku2",
|
||||
GroupIDSingleSku1: "group-with-sku1",
|
||||
GroupIDSingleSku2: "group-with-sku2",
|
||||
GroupIDTwoSkus: "group-with-two-skus",
|
||||
GroupIDThreeSkus: "group-with-three-skus",
|
||||
}
|
||||
}
|
||||
|
||||
func (helper cumulationTestHelper) cleanupTestData(t *testing.T) {
|
||||
assert.NoError(t, RemoveAllGroups())
|
||||
assert.NoError(t, RemoveAllPriceRules())
|
||||
assert.NoError(t, RemoveAllVouchers())
|
||||
ClearCache() // reset cache for catalogue calculations
|
||||
}
|
||||
func (helper cumulationTestHelper) cleanupAndRecreateTestData(t *testing.T) {
|
||||
helper.cleanupTestData(t)
|
||||
productsInGroups := make(map[string][]string)
|
||||
productsInGroups[helper.GroupIDSingleSku1] = []string{helper.Sku1}
|
||||
productsInGroups[helper.GroupIDSingleSku2] = []string{helper.Sku2}
|
||||
productsInGroups[helper.GroupIDTwoSkus] = []string{helper.Sku1, helper.Sku2}
|
||||
productsInGroups[helper.GroupIDThreeSkus] = []string{helper.Sku1, helper.Sku2, helper.Sku3}
|
||||
|
||||
helper.createMockCustomerGroups(t, []string{helper.CustomerGroupRegular, helper.CustomerGroupEmployee})
|
||||
helper.createMockProductGroups(t, productsInGroups)
|
||||
}
|
||||
|
||||
func (helper cumulationTestHelper) createMockProductGroups(t *testing.T, productGroups map[string][]string) {
|
||||
for groupID, items := range productGroups {
|
||||
group := new(Group)
|
||||
group.Type = ProductGroup
|
||||
group.ID = groupID
|
||||
group.Name = groupID
|
||||
assert.NoError(t, group.AddGroupItemIDsAndPersist(items), "Could not create product groups")
|
||||
}
|
||||
}
|
||||
|
||||
func (helper cumulationTestHelper) createMockCustomerGroups(t *testing.T, customerGroups []string) {
|
||||
for _, groupID := range customerGroups {
|
||||
group := new(Group)
|
||||
group.Type = CustomerGroup
|
||||
group.ID = groupID
|
||||
group.Name = groupID
|
||||
assert.NoError(t, group.AddGroupItemIDsAndPersist([]string{groupID}), "Could not create customer groups")
|
||||
}
|
||||
}
|
||||
|
||||
// createVouchers creates n voucher codes for given Pricerule
|
||||
func (helper cumulationTestHelper) createMockVouchers(t *testing.T, priceRule *PriceRule, n int) []string {
|
||||
vouchers := make([]string, n)
|
||||
for i, _ := range vouchers {
|
||||
voucherCode := "voucher-" + priceRule.ID + "-" + strconv.Itoa(i)
|
||||
voucher := NewVoucher(voucherCode, voucherCode, priceRule, "")
|
||||
assert.NoError(t, voucher.Upsert())
|
||||
vouchers[i] = voucherCode
|
||||
}
|
||||
return vouchers
|
||||
}
|
||||
|
||||
func (helper cumulationTestHelper) getMockArticleCollection() *ArticleCollection {
|
||||
return &ArticleCollection{
|
||||
Articles: []*Article{
|
||||
{
|
||||
ID: helper.Sku1,
|
||||
Price: 10.0,
|
||||
Quantity: 1,
|
||||
AllowCrossPriceCalculation: true,
|
||||
},
|
||||
{
|
||||
ID: helper.Sku2,
|
||||
Price: 20.0,
|
||||
Quantity: 1,
|
||||
AllowCrossPriceCalculation: true,
|
||||
},
|
||||
},
|
||||
CustomerType: helper.CustomerGroupRegular,
|
||||
}
|
||||
}
|
||||
func (helper cumulationTestHelper) setMockEmployeeDiscount10Percent(t *testing.T, name string, includedProductGroupIDS []string) {
|
||||
|
||||
// Create pricerule
|
||||
priceRule := NewPriceRule("PriceRule-EmployeeDiscount-" + name)
|
||||
priceRule.Type = TypePromotionCustomer
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionItemByPercent
|
||||
priceRule.Amount = 10
|
||||
priceRule.IncludedProductGroupIDS = includedProductGroupIDS
|
||||
priceRule.IncludedCustomerGroupIDS = []string{helper.CustomerGroupEmployee}
|
||||
assert.NoError(t, priceRule.Upsert())
|
||||
|
||||
return
|
||||
}
|
||||
func (helper cumulationTestHelper) setMockPriceRuleAndVoucherXPercent(t *testing.T, name string, amount float64, includedProductGroupIDS []string, excludeAlreadyDiscountedItems bool, excludeEmployees bool) string {
|
||||
|
||||
// Create pricerule
|
||||
priceRule := NewPriceRule("PriceRule-" + name)
|
||||
priceRule.Type = TypeVoucher
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionItemByPercent
|
||||
priceRule.Amount = amount
|
||||
priceRule.IncludedProductGroupIDS = includedProductGroupIDS
|
||||
if excludeEmployees {
|
||||
priceRule.IncludedCustomerGroupIDS = []string{helper.CustomerGroupRegular}
|
||||
}
|
||||
priceRule.ExcludeAlreadyDiscountedItemsForVoucher = excludeAlreadyDiscountedItems
|
||||
assert.Nil(t, priceRule.Upsert())
|
||||
|
||||
// Create voucher
|
||||
return helper.createMockVouchers(t, priceRule, 1)[0]
|
||||
}
|
||||
|
||||
func (helper cumulationTestHelper) setMockPriceRuleCrossPrice(t *testing.T, name string, amount float64, isPercent bool, includedProductGroupIDS []string) {
|
||||
|
||||
// Create pricerule
|
||||
priceRule := NewPriceRule("PriceRulePromotionProduct-" + name)
|
||||
priceRule.Type = TypePromotionProduct
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionItemByAbsolute
|
||||
if isPercent {
|
||||
priceRule.Action = ActionItemByPercent
|
||||
}
|
||||
priceRule.Amount = amount
|
||||
priceRule.IncludedProductGroupIDS = includedProductGroupIDS
|
||||
assert.NoError(t, priceRule.Upsert())
|
||||
}
|
||||
func (helper cumulationTestHelper) setMockPriceRuleBuy3Pay2(t *testing.T, name string, includedProductGroupIDS []string) {
|
||||
|
||||
// Create pricerule
|
||||
priceRule := NewPriceRule("PriceRuleBuy3Pay2-" + name)
|
||||
priceRule.Type = TypePromotionOrder
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionBuyXPayY
|
||||
priceRule.X = 3
|
||||
priceRule.Y = 2
|
||||
priceRule.WhichXYFree = XYCheapestFree
|
||||
priceRule.IncludedProductGroupIDS = includedProductGroupIDS
|
||||
assert.NoError(t, priceRule.Upsert())
|
||||
}
|
||||
|
||||
func (helper cumulationTestHelper) setMockPriceRuleAndVoucherAbsoluteCHF20(t *testing.T, cumulate bool) (string, string) {
|
||||
|
||||
// Create pricerule
|
||||
priceRule := NewPriceRule("PriceRule-" + "CartAbsoluteCHF20")
|
||||
priceRule.Type = TypeVoucher
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionCartByAbsolute
|
||||
priceRule.Amount = 20.0
|
||||
priceRule.IncludedProductGroupIDS = []string{helper.GroupIDTwoSkus}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{helper.CustomerGroupRegular}
|
||||
priceRule.ExcludeAlreadyDiscountedItemsForVoucher = false
|
||||
priceRule.CumulateWithOtherVouchers = cumulate
|
||||
assert.NoError(t, priceRule.Upsert())
|
||||
|
||||
// Create vouchers
|
||||
vouchers := helper.createMockVouchers(t, priceRule, 2)
|
||||
return vouchers[0], vouchers[1]
|
||||
}
|
||||
func (helper cumulationTestHelper) setMockPriceRuleAndVoucher10Percent(t *testing.T, cumulate bool) string {
|
||||
|
||||
// Create pricerule
|
||||
priceRule := NewPriceRule("PriceRule-" + "Cart10Percent")
|
||||
priceRule.Type = TypeVoucher
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionItemByPercent
|
||||
priceRule.Amount = 10.0
|
||||
priceRule.IncludedProductGroupIDS = []string{helper.GroupIDTwoSkus}
|
||||
priceRule.IncludedCustomerGroupIDS = []string{helper.CustomerGroupRegular}
|
||||
priceRule.ExcludeAlreadyDiscountedItemsForVoucher = false
|
||||
priceRule.CumulateWithOtherVouchers = cumulate
|
||||
assert.NoError(t, priceRule.Upsert())
|
||||
|
||||
// Create voucher
|
||||
return helper.createMockVouchers(t, priceRule, 1)[0]
|
||||
}
|
||||
|
||||
func (helper cumulationTestHelper) setMockPriceRuleQtyThreshold(t *testing.T, name string, amount float64, threshold float64, includedProductGroupIDS []string) {
|
||||
|
||||
// Create pricerule
|
||||
priceRule := NewPriceRule("PriceRulePromotionQtyThreshold-" + name)
|
||||
priceRule.Type = TypePromotionOrder // TypePromotionProduct would also work here
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionItemByAbsolute
|
||||
priceRule.QtyThreshold = threshold
|
||||
priceRule.Amount = amount
|
||||
priceRule.IncludedProductGroupIDS = includedProductGroupIDS
|
||||
assert.NoError(t, priceRule.Upsert())
|
||||
}
|
||||
func (helper cumulationTestHelper) setMockPriceRuleThresholdAmount(t *testing.T, name string, amount float64, thresholdAmount float64, includedProductGroupIDS []string) {
|
||||
|
||||
// Create pricerule
|
||||
priceRule := NewPriceRule("PriceRulePromotionProductThresholdAmount-" + name)
|
||||
priceRule.Type = TypePromotionOrder // TypePromotionProduct would also work here
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionItemByAbsolute
|
||||
priceRule.Amount = amount
|
||||
priceRule.MinOrderAmount = thresholdAmount
|
||||
priceRule.IncludedProductGroupIDS = includedProductGroupIDS
|
||||
assert.NoError(t, priceRule.Upsert())
|
||||
}
|
||||
|
||||
func (helper cumulationTestHelper) setMockBonusVoucherPriceRule(t *testing.T) (string, string) {
|
||||
|
||||
// Create pricerule
|
||||
priceRule := NewPriceRule("PriceRule-" + "Bonus10CHF")
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Type = TypeBonusVoucher
|
||||
priceRule.Action = ActionCartByAbsolute
|
||||
priceRule.Amount = 10.0
|
||||
|
||||
priceRule.CalculateDiscountedOrderAmount = true
|
||||
priceRule.Priority = 999
|
||||
assert.NoError(t, priceRule.Upsert())
|
||||
|
||||
// Create vouchers
|
||||
vouchers := helper.createMockVouchers(t, priceRule, 2)
|
||||
return vouchers[0], vouchers[1]
|
||||
}
|
||||
|
||||
func (helper cumulationTestHelper) accumulateDiscountsOfItems(discounts OrderDiscounts) float64 {
|
||||
sum := 0.0
|
||||
for _, d := range discounts {
|
||||
sum += d.TotalDiscountAmountApplicable
|
||||
}
|
||||
return sum
|
||||
}
|
||||
@ -1,251 +0,0 @@
|
||||
package pricerule
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/foomo/shop/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type cumulationTestHelper struct{}
|
||||
|
||||
func (helper cumulationTestHelper) getMockArticleCollection() *ArticleCollection {
|
||||
return &ArticleCollection{
|
||||
Articles: []*Article{
|
||||
{
|
||||
ID: Sku1,
|
||||
Price: 10.0,
|
||||
Quantity: 1,
|
||||
AllowCrossPriceCalculation: true,
|
||||
},
|
||||
{
|
||||
ID: Sku2,
|
||||
Price: 20.0,
|
||||
Quantity: 1,
|
||||
AllowCrossPriceCalculation: true,
|
||||
},
|
||||
},
|
||||
CustomerType: CustomerID1,
|
||||
}
|
||||
}
|
||||
func (helper cumulationTestHelper) setMockPriceRuleAndVoucher(t *testing.T, name string, amount float64, includedProductGroupIDS []string, excludeAlreadyDiscountedItems bool) string {
|
||||
|
||||
// PRICERULE
|
||||
priceRule := NewPriceRule("PriceRule-" + name)
|
||||
priceRule.Type = TypeVoucher
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionItemByPercent
|
||||
priceRule.Amount = amount
|
||||
priceRule.IncludedProductGroupIDS = includedProductGroupIDS
|
||||
priceRule.IncludedCustomerGroupIDS = []string{CustomerGroupID1}
|
||||
priceRule.ExcludeAlreadyDiscountedItemsForVoucher = excludeAlreadyDiscountedItems
|
||||
assert.Nil(t, priceRule.Upsert())
|
||||
|
||||
voucherCode := "voucherCode-" + priceRule.ID
|
||||
|
||||
voucher := NewVoucher(voucherCode, voucherCode, priceRule, "")
|
||||
assert.Nil(t, voucher.Upsert())
|
||||
return voucherCode
|
||||
}
|
||||
|
||||
func (helper cumulationTestHelper) setMockPriceRuleCrossPrice(t *testing.T, name string, amount float64, includedProductGroupIDS []string) {
|
||||
// PRICERULE 0
|
||||
priceRule := NewPriceRule("PriceRulePromotionProduct-" + name)
|
||||
priceRule.Type = TypePromotionProduct
|
||||
priceRule.Description = priceRule.Name
|
||||
priceRule.Action = ActionItemByAbsolute
|
||||
priceRule.Amount = amount
|
||||
priceRule.IncludedProductGroupIDS = includedProductGroupIDS
|
||||
assert.Nil(t, priceRule.Upsert())
|
||||
}
|
||||
|
||||
func TestCumulationTwoVouchers_OnePerSku(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Expected result: one of the vouchers is applied to each item
|
||||
Init(t)
|
||||
|
||||
helper := cumulationTestHelper{}
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucher(t, "voucher-sku1", 10.0, []string{GroupIDSingleSku1}, false)
|
||||
voucherCode2 := helper.setMockPriceRuleAndVoucher(t, "voucher-sku2", 10.0, []string{GroupIDSingleSku2}, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.Nil(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 10% on 30 CHF
|
||||
assert.Equal(t, 3.0, summary.TotalDiscountApplicable)
|
||||
}
|
||||
func TestCumulationTwoVouchers_BothForSameSku(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Both voucher are only valid for one of the items
|
||||
// Expected result: One voucher is being applied, the other one is dismissed
|
||||
|
||||
Init(t)
|
||||
|
||||
helper := cumulationTestHelper{}
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucher(t, "voucher-sku1", 10.0, []string{GroupIDSingleSku1}, false)
|
||||
voucherCode2 := helper.setMockPriceRuleAndVoucher(t, "voucher-sku2", 10.0, []string{GroupIDSingleSku1}, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.Nil(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// only one voucher should be applied => 1 CHF
|
||||
assert.Equal(t, 1.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationTwoVouchers_BothForBothSkus(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Both voucher are valid for both of the items
|
||||
// Expected result: The better voucher is applied to both items
|
||||
|
||||
Init(t)
|
||||
|
||||
helper := cumulationTestHelper{}
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucher(t, "voucher-1", 5.0, []string{GroupIDTwoSkus}, false)
|
||||
voucherCode2 := helper.setMockPriceRuleAndVoucher(t, "voucher-2", 10.0, []string{GroupIDTwoSkus}, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.Nil(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 10% on 30 CHF
|
||||
assert.Equal(t, 3.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationTwoVouchers_BothForSameSku_AdditonalCrossPrice(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Both voucher are only valid for one of the items
|
||||
// Expected result: - both items discounted by product promo
|
||||
// - One voucher is being applied, the other one is dismissed
|
||||
|
||||
Init(t)
|
||||
|
||||
helper := cumulationTestHelper{}
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
helper.setMockPriceRuleCrossPrice(t, "crossprice1", 5.0, []string{GroupIDTwoSkus})
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucher(t, "voucher-sku1", 5.0, []string{GroupIDSingleSku1}, false)
|
||||
voucherCode2 := helper.setMockPriceRuleAndVoucher(t, "voucher-sku2", 10.0, []string{GroupIDSingleSku1}, false)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1, voucherCode2}, nil, 0.05, nil)
|
||||
assert.Nil(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// Sku1: 5 + 0.5, Sku2: 5 => 10.5
|
||||
assert.Equal(t, 10.5, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationProductPromo(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Expected result: - only better cross price should be applied
|
||||
|
||||
Init(t)
|
||||
|
||||
helper := cumulationTestHelper{}
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
helper.setMockPriceRuleCrossPrice(t, "crossprice1", 2.0, []string{GroupIDTwoSkus})
|
||||
helper.setMockPriceRuleCrossPrice(t, "crossprice2", 5.0, []string{GroupIDTwoSkus})
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{}, []string{}, 0.05, nil)
|
||||
assert.Nil(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// 5+5 (5 on each product) = 10 CHF
|
||||
assert.Equal(t, 10.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
|
||||
func TestCumulationForExcludeVoucherOnCrossPriceWebhop(t *testing.T) {
|
||||
// Cart with 2 Items
|
||||
// Expected result: voucher is only applied to sku2. Sku1 is skipped due to existing webshop cross-price
|
||||
|
||||
Init(t)
|
||||
|
||||
helper := cumulationTestHelper{}
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
helper.setMockPriceRuleCrossPrice(t, "crossprice1", 5.0, []string{GroupIDSingleSku1})
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucher(t, "voucher-1", 10.0, []string{GroupIDTwoSkus}, true)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.Nil(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// Sku1: 5, Sku2: 2
|
||||
assert.Equal(t, 7.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
func TestCumulationForExcludeVoucherOnCrossPriceSAP(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Expected result: voucher is only applied to sku2. Sku1 is skipped due to existing SAP cross-price
|
||||
// (indicated by AllowCrossPriceCalculation == false)
|
||||
|
||||
Init(t)
|
||||
|
||||
helper := cumulationTestHelper{}
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
for i, article := range articleCollection.Articles {
|
||||
if i == 0 {
|
||||
article.AllowCrossPriceCalculation = false // this is false if there already is a SAP crossprice
|
||||
}
|
||||
}
|
||||
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucher(t, "voucher-1", 10.0, []string{GroupIDTwoSkus}, true)
|
||||
|
||||
discounts, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.Nil(t, errApply)
|
||||
utils.PrintJSON(discounts)
|
||||
utils.PrintJSON(summary)
|
||||
|
||||
// Sku2: 2 CHF
|
||||
assert.Equal(t, 2.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
|
||||
func TestCumulationExcludeStaff(t *testing.T) {
|
||||
|
||||
// Cart with 2 Items
|
||||
// Expected result: only regular customer gets discount
|
||||
Init(t)
|
||||
|
||||
helper := cumulationTestHelper{}
|
||||
articleCollection := helper.getMockArticleCollection()
|
||||
|
||||
voucherCode1 := helper.setMockPriceRuleAndVoucher(t, "voucher-sku1", 10.0, []string{GroupIDTwoSkus}, false)
|
||||
|
||||
// Get Discuonts for regular customer
|
||||
_, summary, errApply := ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.Nil(t, errApply)
|
||||
|
||||
// 10% on 30 CHF
|
||||
assert.Equal(t, 3.0, summary.TotalDiscountApplicable)
|
||||
|
||||
// Change customer type => no discount
|
||||
articleCollection.CustomerType = "employee"
|
||||
_, summary, errApply = ApplyDiscounts(articleCollection, nil, []string{voucherCode1}, nil, 0.05, nil)
|
||||
assert.Nil(t, errApply)
|
||||
|
||||
// No discount for non-regulat customer
|
||||
assert.Equal(t, 0.0, summary.TotalDiscountApplicable)
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user