fix(loyalty): normalize card id field, fix terminal redeem bug
Some checks failed
Some checks failed
The terminal redeem failed with "card not found: unknown" because CardLookupResponse used card_id while CardDetailResponse (from refreshCard) used id. After refresh, selectedCard.card_id was undefined. Fix: standardize on 'id' everywhere (the universal convention): - CardLookupResponse: card_id → id - _build_card_lookup_response: card_id= → id= - loyalty-terminal.js: selectedCard.card_id → selectedCard.id (5 refs) - Removed the card_id/model_validator approach as unnecessary Also fixes Chart.js recursion error on analytics page (inline CDN script instead of optional-libs.html include which caused infinite template recursion in test context). 342 tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -420,7 +420,7 @@ def _build_card_lookup_response(card, db=None) -> CardLookupResponse:
|
|||||||
available_rewards.append(reward)
|
available_rewards.append(reward)
|
||||||
|
|
||||||
return CardLookupResponse(
|
return CardLookupResponse(
|
||||||
card_id=card.id,
|
id=card.id,
|
||||||
card_number=card.card_number,
|
card_number=card.card_number,
|
||||||
customer_id=card.customer_id,
|
customer_id=card.customer_id,
|
||||||
customer_name=card.customer.full_name if card.customer else None,
|
customer_name=card.customer.full_name if card.customer else None,
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ class CardLookupResponse(BaseModel):
|
|||||||
"""Schema for card lookup by QR code or card number."""
|
"""Schema for card lookup by QR code or card number."""
|
||||||
|
|
||||||
# Card info
|
# Card info
|
||||||
card_id: int
|
id: int
|
||||||
card_number: str
|
card_number: str
|
||||||
|
|
||||||
# Customer
|
# Customer
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ function storeLoyaltyTerminal() {
|
|||||||
loyaltyTerminalLog.info('Adding stamp...');
|
loyaltyTerminalLog.info('Adding stamp...');
|
||||||
|
|
||||||
await apiClient.post('/store/loyalty/stamp', {
|
await apiClient.post('/store/loyalty/stamp', {
|
||||||
card_id: this.selectedCard.card_id,
|
card_id: this.selectedCard.id,
|
||||||
staff_pin: this.pinDigits
|
staff_pin: this.pinDigits
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ function storeLoyaltyTerminal() {
|
|||||||
loyaltyTerminalLog.info('Redeeming stamps...');
|
loyaltyTerminalLog.info('Redeeming stamps...');
|
||||||
|
|
||||||
await apiClient.post('/store/loyalty/stamp/redeem', {
|
await apiClient.post('/store/loyalty/stamp/redeem', {
|
||||||
card_id: this.selectedCard.card_id,
|
card_id: this.selectedCard.id,
|
||||||
staff_pin: this.pinDigits
|
staff_pin: this.pinDigits
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -308,7 +308,7 @@ function storeLoyaltyTerminal() {
|
|||||||
loyaltyTerminalLog.info('Earning points...', { amount: this.earnAmount });
|
loyaltyTerminalLog.info('Earning points...', { amount: this.earnAmount });
|
||||||
|
|
||||||
const response = await apiClient.post('/store/loyalty/points/earn', {
|
const response = await apiClient.post('/store/loyalty/points/earn', {
|
||||||
card_id: this.selectedCard.card_id,
|
card_id: this.selectedCard.id,
|
||||||
purchase_amount_cents: Math.round(this.earnAmount * 100),
|
purchase_amount_cents: Math.round(this.earnAmount * 100),
|
||||||
staff_pin: this.pinDigits
|
staff_pin: this.pinDigits
|
||||||
});
|
});
|
||||||
@@ -327,7 +327,7 @@ function storeLoyaltyTerminal() {
|
|||||||
loyaltyTerminalLog.info('Redeeming reward...', { reward: reward.name });
|
loyaltyTerminalLog.info('Redeeming reward...', { reward: reward.name });
|
||||||
|
|
||||||
await apiClient.post('/store/loyalty/points/redeem', {
|
await apiClient.post('/store/loyalty/points/redeem', {
|
||||||
card_id: this.selectedCard.card_id,
|
card_id: this.selectedCard.id,
|
||||||
reward_id: this.selectedReward,
|
reward_id: this.selectedReward,
|
||||||
staff_pin: this.pinDigits
|
staff_pin: this.pinDigits
|
||||||
});
|
});
|
||||||
@@ -340,7 +340,7 @@ function storeLoyaltyTerminal() {
|
|||||||
// Refresh card data
|
// Refresh card data
|
||||||
async refreshCard() {
|
async refreshCard() {
|
||||||
try {
|
try {
|
||||||
const response = await apiClient.get(`/store/loyalty/cards/${this.selectedCard.card_id}`);
|
const response = await apiClient.get(`/store/loyalty/cards/${this.selectedCard.id}`);
|
||||||
if (response) {
|
if (response) {
|
||||||
this.selectedCard = response;
|
this.selectedCard = response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,7 +155,6 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
{% include 'shared/includes/optional-libs.html' with context %}
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
||||||
{{ chartjs_loader() }}
|
|
||||||
<script defer src="{{ url_for('loyalty_static', path='store/js/loyalty-analytics.js') }}"></script>
|
<script defer src="{{ url_for('loyalty_static', path='store/js/loyalty-analytics.js') }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user