feat: integer cents money handling, order page fixes, and vendor filter persistence
Money Handling Architecture: - Store all monetary values as integer cents (€105.91 = 10591) - Add app/utils/money.py with Money class and conversion helpers - Add static/shared/js/money.js for frontend formatting - Update all database models to use _cents columns (Product, Order, etc.) - Update CSV processor to convert prices to cents on import - Add Alembic migration for Float to Integer conversion - Create .architecture-rules/money.yaml with 7 validation rules - Add docs/architecture/money-handling.md documentation Order Details Page Fixes: - Fix customer name showing 'undefined undefined' - use flat field names - Fix vendor info empty - add vendor_name/vendor_code to OrderDetailResponse - Fix shipping address using wrong nested object structure - Enrich order detail API response with vendor info Vendor Filter Persistence Fixes: - Fix orders.js: restoreSavedVendor now sets selectedVendor and filters - Fix orders.js: init() only loads orders if no saved vendor to restore - Fix marketplace-letzshop.js: restoreSavedVendor calls selectVendor() - Fix marketplace-letzshop.js: clearVendorSelection clears TomSelect dropdown - Align vendor selector placeholder text between pages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -30,11 +30,19 @@ function adminSettings() {
|
||||
in_app_enabled: true,
|
||||
critical_only: false
|
||||
},
|
||||
shippingSettings: {
|
||||
carrier_greco_label_url: 'https://dispatchweb.fr/Tracky/Home/',
|
||||
carrier_colissimo_label_url: '',
|
||||
carrier_xpresslogistics_label_url: ''
|
||||
},
|
||||
|
||||
async init() {
|
||||
try {
|
||||
settingsLog.info('=== SETTINGS PAGE INITIALIZING ===');
|
||||
await this.loadLogSettings();
|
||||
await Promise.all([
|
||||
this.loadLogSettings(),
|
||||
this.loadShippingSettings()
|
||||
]);
|
||||
} catch (error) {
|
||||
settingsLog.error('Init failed:', error);
|
||||
this.error = 'Failed to initialize settings page';
|
||||
@@ -44,7 +52,10 @@ function adminSettings() {
|
||||
async refresh() {
|
||||
this.error = null;
|
||||
this.successMessage = null;
|
||||
await this.loadLogSettings();
|
||||
await Promise.all([
|
||||
this.loadLogSettings(),
|
||||
this.loadShippingSettings()
|
||||
]);
|
||||
},
|
||||
|
||||
async loadLogSettings() {
|
||||
@@ -136,6 +147,75 @@ function adminSettings() {
|
||||
} finally {
|
||||
this.saving = false;
|
||||
}
|
||||
},
|
||||
|
||||
async loadShippingSettings() {
|
||||
try {
|
||||
// Load each carrier setting
|
||||
const carriers = ['greco', 'colissimo', 'xpresslogistics'];
|
||||
for (const carrier of carriers) {
|
||||
try {
|
||||
const key = `carrier_${carrier}_label_url`;
|
||||
const data = await apiClient.get(`/admin/settings/${key}`);
|
||||
if (data && data.value) {
|
||||
this.shippingSettings[key] = data.value;
|
||||
}
|
||||
} catch (error) {
|
||||
// Setting doesn't exist yet, use default
|
||||
settingsLog.debug(`Setting carrier_${carrier}_label_url not found, using default`);
|
||||
}
|
||||
}
|
||||
settingsLog.info('Shipping settings loaded:', this.shippingSettings);
|
||||
} catch (error) {
|
||||
settingsLog.error('Failed to load shipping settings:', error);
|
||||
// Don't show error for missing settings, just use defaults
|
||||
}
|
||||
},
|
||||
|
||||
async saveShippingSettings() {
|
||||
this.saving = true;
|
||||
this.error = null;
|
||||
this.successMessage = null;
|
||||
|
||||
try {
|
||||
// Save each carrier setting using upsert
|
||||
const carriers = [
|
||||
{ key: 'carrier_greco_label_url', name: 'Greco' },
|
||||
{ key: 'carrier_colissimo_label_url', name: 'Colissimo' },
|
||||
{ key: 'carrier_xpresslogistics_label_url', name: 'XpressLogistics' }
|
||||
];
|
||||
|
||||
for (const carrier of carriers) {
|
||||
await apiClient.post('/admin/settings/upsert', {
|
||||
key: carrier.key,
|
||||
value: this.shippingSettings[carrier.key] || '',
|
||||
category: 'shipping',
|
||||
value_type: 'string',
|
||||
description: `Label URL prefix for ${carrier.name} carrier`
|
||||
});
|
||||
}
|
||||
|
||||
this.successMessage = 'Shipping settings saved successfully';
|
||||
|
||||
// Auto-hide success message after 5 seconds
|
||||
setTimeout(() => {
|
||||
this.successMessage = null;
|
||||
}, 5000);
|
||||
|
||||
settingsLog.info('Shipping settings saved:', this.shippingSettings);
|
||||
} catch (error) {
|
||||
settingsLog.error('Failed to save shipping settings:', error);
|
||||
this.error = error.response?.data?.detail || 'Failed to save shipping settings';
|
||||
} finally {
|
||||
this.saving = false;
|
||||
}
|
||||
},
|
||||
|
||||
getShippingLabelUrl(carrier, shipmentNumber) {
|
||||
// Helper to generate full label URL
|
||||
const prefix = this.shippingSettings[`carrier_${carrier}_label_url`] || '';
|
||||
if (!prefix || !shipmentNumber) return null;
|
||||
return prefix + shipmentNumber;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user