Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pz/qualifications api #254

Merged
merged 19 commits into from
Jan 9, 2024

Conversation

p-zielinski
Copy link
Contributor

@p-zielinski p-zielinski commented Nov 9, 2023


'@voucherify/sdk': minor

Add support for few endpoints of Loyalties API.

  • Added support for new endpoints: POST /v1/qualifications, POST /client/v1/qualifications (examples of usage available in readme.md)
  • New exported types/interfaces: InapplicableTo, Referrer, ReferrerWithSummaryLoyaltyReferrals, Customer, CustomerWithSummaryLoyaltyReferrals, CustomerSummary, CustomerSummaryRedemptions, CustomerSummaryOrders, CustomerLoyalty, CustomerReferrals, Discount, DiscountAmount_, DiscountUnit_, DiscountUnitBase_, DiscountUnitMultiple_, DiscountPercent_, DiscountFixed_, Order, OrderItem, OrderCalculated, OrderRedemptions, OrderItemCalculated, QualificationsCheckEligibilityRequestBody, QualificationsCheckEligibilityResponseBody, QualificationsFiltersFields, QualificationsFiltersCondition, QualificationsFieldConditions, QualificationsRedeemablesResponse, QualificationsStackingRulesResponse, QualificationsRedeemable, QualificationsRedeemableBase, RedeemableSingleResultResponse, ValidationRulesAssignmentsList,
  • Added optional properties to ApplicableTo: product_id, product_source_id, quantity_limit, aggregated_quantity_limit, amount_limit, aggregated_amount_limit, order_item_indices
  • Added required property: data_ref: 'data' to ApplicableToResultList // NOTE: as this type is only used in responses, this is not a breaking change.
  • Added optional properties to CustomerRequest: birthday and birthdate

@p-zielinski p-zielinski marked this pull request as ready for review November 10, 2023 10:10
@p-zielinski
Copy link
Contributor Author

@marcin-slezak
PR is ready to review, thanks

Copy link
Contributor

@weronika-kurczyna weronika-kurczyna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in general, I don't see any errors here, the only thing that puzzles me is the issue with

export type QualificationsRedeemableSingleResponse = QualificationsRedeemableSingleResponseBase & {
	redeemables?: QualificationsRedeemableSingleResponseBase[]
}

But if you are sure about it, I have no comments

packages/sdk/src/types/Qualifications.ts Outdated Show resolved Hide resolved
}

export type QualificationsRedeemableSingleResponse = QualificationsRedeemableSingleResponseBase & {
redeemables?: QualificationsRedeemableSingleResponseBase[]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so in this case we will get a repeated QualificationsRedeemableSingleResponseBase type in redeemables? I'm asking because I couldn't get the result with the redeemables even though I sent "options": { "expand": ["redeemable"] } and it seems strange to me 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and the doc shows that it should return redeemables' metadata (?)
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{
    "redeemables": {
        "object": "list",
        "data_ref": "data",
        "data": [
            {
                "id": "string",
                "object": "campaign",
                "created_at": "2022-03-09T11:19:04.819Z",
                "result": {
                    "discount": {
                        "type": "AMOUNT",
                        "amount_off": 0,
                        "amount_off_formula": "string",
                        "aggregated_amount_limit": 0,
                        "effect": "APPLY_TO_ORDER",
                        "is_dynamic": true
                    },
                    "gift": {
                        "balance": 0,
                        "credits": 0
                    },
                    "loyalty_card": {
                        "points": 7000,
                        "balance": 6970,
                        "exchange_ratio": 0,
                        "points_ratio": 0,
                        "transfers": [
                            {
                                "code": "string",
                                "points": 0,
                                "reason": "string",
                                "source_id": "string"
                            }
                        ]
                    },
                    "error": {
                        "code": 0,
                        "key": "string",
                        "message": "string",
                        "details": "string",
                        "request_id": "v-0a885062c80375740f",
                        "resource_id": "rf_0c5d710a87c8a31f86",
                        "resource_type": "voucher"
                    }
                },
                "order": {},
                "validation_rule_id": "string",
                "applicable_to": {
                    "data": [
                        {
                            "object": "product",
                            "id": "string",
                            "source_id": "string",
                            "product_id": "string",
                            "product_source_id": "string",
                            "strict": true,
                            "price": 0,
                            "price_formula": 0,
                            "effect": "APPLY_TO_EVERY",
                            "quantity_limit": 0,
                            "aggregated_quantity_limit": 0,
                            "amount_limit": 0,
                            "aggregated_amount_limit": 0,
                            "order_item_indices": [
                                0
                            ]
                        }
                    ],
                    "total": 0,
                    "object": "list",
                    "data_ref": "data"
                },
                "inapplicable_to": {
                    "data": [
                        {
                            "object": "product",
                            "id": "string",
                            "source_id": "string",
                            "product_id": "string",
                            "product_source_id": "string",
                            "strict": true,
                            "price": 0,
                            "price_formula": 0,
                            "effect": "APPLY_TO_EVERY",
                            "quantity_limit": 0,
                            "aggregated_quantity_limit": 0,
                            "amount_limit": 0,
                            "aggregated_amount_limit": 0,
                            "order_item_indices": [
                                0
                            ]
                        }
                    ],
                    "total": 0,
                    "object": "list",
                    "data_ref": "data"
                },
                "metadata": {},
                "categories": [
                    {
                        "id": "string",
                        "name": "string",
                        "hierarchy": 0,
                        "object": "category",
                        "created_at": "2022-07-14T10:45:13.156Z",
                        "updated_at": "2022-08-16T10:52:08.094Z",
                        "stacking_rules_type": "JOINT"
                    }
                ],
                "banner": "Order Paid - You will get 100 points",
                "name": "promotion_tier_get_points",
                "campaign_name": "PromotionCampaign",
                "campaign_id": "camp_Mow7u4gSxagLlZ2oDQ01ZS5N",
                "validation_rules_assignments": {
                    "object": "list",
                    "data_ref": "data",
                    "data": [
                        {
                            "id": "asgm_LnY1g7UNFA9KyDrD",
                            "rule_id": "val_3gPNA6SnH4ae",
                            "related_object_id": "camp_CZOnEGiZfwIKWmSjhIoIT7Ol",
                            "related_object_type": "campaign",
                            "object": "validation_rules_assignment",
                            "validation_status": "PARTIALLY_VALID",
                            "validation_omitted_rules": [
                                "1"
                            ]
                        }
                    ],
                    "total": 0
                },
                "redeemables": [
                    {
                        "id": "string",
                        "object": "campaign",
                        "created_at": "2022-03-09T11:19:04.819Z",
                        "result": {
                            "discount": {
                                "type": "AMOUNT",
                                "amount_off": 0,
                                "amount_off_formula": "string",
                                "aggregated_amount_limit": 0,
                                "effect": "APPLY_TO_ORDER",
                                "is_dynamic": true
                            },
                            "gift": {
                                "balance": 0,
                                "credits": 0
                            },
                            "loyalty_card": {
                                "points": 7000,
                                "balance": 6970,
                                "exchange_ratio": 0,
                                "points_ratio": 0,
                                "transfers": [
                                    {
                                        "code": "string",
                                        "points": 0,
                                        "reason": "string",
                                        "source_id": "string"
                                    }
                                ]
                            },
                            "error": {
                                "code": 0,
                                "key": "string",
                                "message": "string",
                                "details": "string",
                                "request_id": "v-0a885062c80375740f",
                                "resource_id": "rf_0c5d710a87c8a31f86",
                                "resource_type": "voucher"
                            }
                        },
                        "order": {},
                        "validation_rule_id": "string",
                        "applicable_to": {
                            "data": [
                                {
                                    "object": "product",
                                    "id": "string",
                                    "source_id": "string",
                                    "product_id": "string",
                                    "product_source_id": "string",
                                    "strict": true,
                                    "price": 0,
                                    "price_formula": 0,
                                    "effect": "APPLY_TO_EVERY",
                                    "quantity_limit": 0,
                                    "aggregated_quantity_limit": 0,
                                    "amount_limit": 0,
                                    "aggregated_amount_limit": 0,
                                    "order_item_indices": [
                                        0
                                    ]
                                }
                            ],
                            "total": 0,
                            "object": "list",
                            "data_ref": "data"
                        },
                        "inapplicable_to": {
                            "data": [
                                {
                                    "object": "product",
                                    "id": "string",
                                    "source_id": "string",
                                    "product_id": "string",
                                    "product_source_id": "string",
                                    "strict": true,
                                    "price": 0,
                                    "price_formula": 0,
                                    "effect": "APPLY_TO_EVERY",
                                    "quantity_limit": 0,
                                    "aggregated_quantity_limit": 0,
                                    "amount_limit": 0,
                                    "aggregated_amount_limit": 0,
                                    "order_item_indices": [
                                        0
                                    ]
                                }
                            ],
                            "total": 0,
                            "object": "list",
                            "data_ref": "data"
                        },
                        "metadata": {},
                        "categories": [
                            {
                                "id": "string",
                                "name": "string",
                                "hierarchy": 0,
                                "object": "category",
                                "created_at": "2022-07-14T10:45:13.156Z",
                                "updated_at": "2022-08-16T10:52:08.094Z",
                                "stacking_rules_type": "JOINT"
                            }
                        ],
                        "banner": "Order Paid - You will get 100 points",
                        "name": "promotion_tier_get_points",
                        "campaign_name": "PromotionCampaign",
                        "campaign_id": "camp_Mow7u4gSxagLlZ2oDQ01ZS5N",
                        "validation_rules_assignments": {
                            "object": "list",
                            "data_ref": "data",
                            "data": [
                                {
                                    "id": "asgm_LnY1g7UNFA9KyDrD",
                                    "rule_id": "val_3gPNA6SnH4ae",
                                    "related_object_id": "camp_CZOnEGiZfwIKWmSjhIoIT7Ol",
                                    "related_object_type": "campaign",
                                    "object": "validation_rules_assignment",
                                    "validation_status": "PARTIALLY_VALID",
                                    "validation_omitted_rules": [
                                        "1"
                                    ]
                                }
                            ],
                            "total": 0
                        }
                    }
                ]
            }
        ],
        "total": 5,
        "has_more": true,
        "more_starting_after": "2023-10-31T12:13:16.374Z"
    },
    "tracking_id": "string",
    "order": {},
    "stacking_rules": {
        "redeemables_limit": 30,
        "applicable_redeemables_limit": 5,
        "applicable_exclusive_redeemables_limit": 1,
        "exclusive_categories": [
            "string"
        ],
        "joint_categories": [
            "string"
        ]
    }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just check it. You should create promotion with promotion stack and use specific scenario
Payload:

{
    "mode": "BASIC",
    "scenario" : "PROMOTION_STACKS"
}

Response:

{
    "redeemables": {
        "object": "list",
        "data_ref": "data",
        "data": [
            {
                "id": "stack_Zb22FW0F4UAzz9heNaI1XnCj",
                "object": "promotion_stack",
                "created_at": "2023-11-20T09:59:29.360Z",
                "redeemables": [
                    {
                        "id": "promo_DJGQ62yKY3oy3Wkp9C48ShHi",
                        "object": "promotion_tier",
                        "created_at": "2023-11-20T09:59:28.265Z",
                        "result": {
                            "discount": {
                                "type": "AMOUNT",
                                "effect": "APPLY_TO_ORDER",
                                "amount_off": 2000
                            }
                        },
                        "applicable_to": {
                            "data": [],
                            "total": 0,
                            "data_ref": "data",
                            "object": "list"
                        },
                        "inapplicable_to": {
                            "data": [],
                            "total": 0,
                            "data_ref": "data",
                            "object": "list"
                        }
                    }
                ]
            },
            {
                "id": "stack_H9RSuQp6T97jLiSuiCAh2Rbd",
                "object": "promotion_stack",
                "created_at": "2023-11-20T09:59:28.777Z",
                "redeemables": [
                    {
                        "id": "promo_zHXP28kq5lXppzf95likISQJ",
                        "object": "promotion_tier",
                        "created_at": "2023-11-20T09:59:28.054Z",
                        "result": {
                            "discount": {
                                "type": "AMOUNT",
                                "effect": "APPLY_TO_ORDER",
                                "amount_off": 1000
                            }
                        },
                        "applicable_to": {
                            "data": [],
                            "total": 0,
                            "data_ref": "data",
                            "object": "list"
                        },
                        "inapplicable_to": {
                            "data": [],
                            "total": 0,
                            "data_ref": "data",
                            "object": "list"
                        }
                    }
                ]
            }
        ],
        "total": 2,
        "has_more": false
    },
    "stacking_rules": {
        "redeemables_limit": 3,
        "applicable_redeemables_limit": 1,
        "applicable_exclusive_redeemables_limit": 1,
        "exclusive_categories": [],
        "joint_categories": []
    }
}


// domain types

// didn't want to make major changes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏼

@@ -92,3 +92,118 @@ export interface OrdersListResponse {
data_ref: 'orders'
orders: OrdersGetResponse[]
}

//domain types
export type OrderRequest = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the idea of naming the domain type with postfix request, response etc.
BUT at the same time, I have no idea how to create it differently :)
At first I would probably create a type: QualificationsCheckEligibilityOrderResponse/Request but I understand that OrderRequest and OrderResponse are different and can be used elsewhere in the future, so creating just the Order type is impossible here 👍🏼

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we have learned while working on openAPI, this patern must be used.
Domain types very often differ if object is used in requests or responses. Until someone will give a better solution, it must be like that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what?

Copy link
Contributor Author

@p-zielinski p-zielinski Nov 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The models often differ depending on whether they are used in requests or responses (i.e., the fields are different). This means that if we want to create domain types, we have to create different domain types depending on whether we use them in requests or responses. This is the system we have adopted when creating OpenAPI.


Modele często różnią się w zależności czy są używane w zapytaniach czy odpowiedziach (czytaj. pola są różne).
Ozacza to, że jeżeli chcemy tworzyć typy domenowe musimy tworzyć typy domenowe różne zależnie od tego czy używamy ich w zapytaniach czy odpowiedziach.
Taki system przyjeliśmy tworząc OpenAPI.

@marcin-slezak marcin-slezak merged commit 8df2fed into voucherifyio:main Jan 9, 2024
1 check passed
@github-actions github-actions bot mentioned this pull request Jan 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants