diff --git a/README.md b/README.md index f630c30..2c843d2 100644 --- a/README.md +++ b/README.md @@ -4,71 +4,50 @@ This module enhances the display of decimal numbers in Odoo by styling the decim ## Features -- Wraps decimal parts in a CSS class for custom styling -- Works across all numeric field types (float, monetary, percentage, etc.) -- **Fixed**: Proper decimal formatting in inventory detailed operations -- Enhanced support for stock moves and inventory operations -- Handles escaped HTML markup properly in list views +- **Visual Enhancement**: Decimal parts are styled to be smaller (80% font size) and slightly transparent (0.7 opacity), making large numbers easier to read. +- **Universal Application**: Works across **all** views (List, Form, Kanban, Pivot, etc.) and all fields (Float, Monetary, Quantity). +- **Non-Invasive Architecture**: Uses a safe DOM Observer approach instead of patching Odoo's internal JS formatters. This ensures maximum compatibility with other modules and Odoo updates. +- **Localization Aware**: Correctly handles decimal separators (dot or comma) based on the user's language settings. -## Recent Fixes +## Technical Details -### Inventory Operations Fix -- **Issue**: Decimal formatting was not working in inventory detailed operations -- **Root Cause**: Previous implementation stripped decimal formatting from stock moves to avoid HTML escaping issues -- **Solution**: - - Improved markup handling to preserve decimal formatting while avoiding escaping issues - - Added specific patches for stock move line renderers - - Enhanced the `wrapDecimal` function to handle inventory-specific cases - - Added proper view inheritance for stock move line views +### Architecture +The module has been refactored to use a **MutationObserver** approach: +1. **Global Observer**: A `MutationObserver` watches the document body for changes. +2. **Safe Text Scanning**: It scans text nodes using a `TreeWalker` to find numbers. +3. **Regex Matching**: It uses a strict Regular Expression to identify decimal parts. + - It dynamically builds the regex using Odoo's `localization.decimalPoint` setting. + - Example (English): Matches `123.45` (.45 is styled). + - Example (Indonesian): Matches `123,45` (,45 is styled). + - **Smart Exclusion**: It intelligently ignores thousands separators (e.g., `1,200` is **not** matched in English/US locale). +4. **DOM Wrapping**: Matches are wrapped in a `` element for styling. -### Technical Changes -1. **Enhanced List View Patch**: Instead of stripping formatting from stock moves, now properly handles escaped HTML -2. **New Stock Move Patch**: Added specific handling for stock move line renderers and enhanced formatter registry -3. **Improved wrapDecimal Function**: Better regex handling for various number formats -4. **Enhanced Formatter Registry**: Comprehensive patching of all numeric formatters used in inventory -5. **Added Stock Dependency**: Module now depends on stock module for proper integration +### Advantages +- **No Conflicts**: Does not override `formatFloat` or `formatMonetary` functions, avoiding conflicts with other modules that modify formatting. +- **Robust**: Works even on custom widgets or non-standard views, as long as the number is rendered as text. ## Usage -The module automatically applies decimal styling to all numeric fields. The decimal part will appear smaller and slightly transparent compared to the integer part. +The module automatically applies decimal styling to all numeric fields. No configuration is required. ## Debugging -### Console Debugging -1. Open browser developer tools (F12) -2. Go to Console tab -3. Look for messages starting with: - - "Web Decimal Style module loaded successfully" - - "Universal Decimal Patch: Formatting" - - "Stock Operations: Applying decimal formatting" +### Console +You can verify the module is running by checking the browser console: +- Look for: `"Web Decimal Style: Loading DOM Decorator observer..."` -### Manual Testing -In the browser console, you can test the decimal formatting function: -```javascript -// Test the wrapDecimal function -testDecimalStyle('123.45') -``` - -### Visual Debugging -The CSS includes a debug indicator (🔸) that appears before each decimal part. This is currently enabled to help identify when decimal formatting is applied. - -### Troubleshooting Steps -1. **Check module loading**: Look for "Web Decimal Style module loaded successfully" in console -2. **Check field detection**: Look for logging messages when viewing inventory operations -3. **Verify decimal detection**: The module should detect values with decimal points (e.g., "123.45") -4. **Check CSS application**: Look for `` elements in the HTML - -If decimal formatting is not working: -1. Refresh the page after module update -2. Clear browser cache -3. Check browser console for JavaScript errors -4. Verify the module is properly installed and upgraded +### Troubleshooting +If styling is not applied: +1. **Check Localization**: Ensure your user's language setting has the correct "Decimal Separator" configured. +2. **Browser Cache**: Clear your browser cache or force refresh (Ctrl+Shift+R) to ensure the new JS is loaded. +3. **Inspect Element**: Right-click a number. You should see the decimal part wrapped in: + ```html + .00 + ``` ## Installation -1. Install the module -2. Restart Odoo -3. Update the module list -4. Install "Web Decimal Style" - -The formatting will be applied automatically to all numeric fields across the system, including inventory operations. \ No newline at end of file +1. Install the module. +2. Restart Odoo. +3. Upgrade the module `web_decimal_style`. +4. Refresh your browser. \ No newline at end of file diff --git a/__manifest__.py b/__manifest__.py index 1e5c86c..d9b9306 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -14,6 +14,7 @@ 'web.assets_backend': [ 'web_decimal_style/static/src/css/decimal_style.css', 'web_decimal_style/static/src/core/utils/numbers_patch.js', + 'web_decimal_style/static/src/views/decimal_observer.js', 'web_decimal_style/static/src/views/fields/formatters_patch.js', 'web_decimal_style/static/src/views/tax_totals_patch.js', 'web_decimal_style/static/src/views/fields/float_field.xml', diff --git a/static/src/core/utils/numbers_patch.js b/static/src/core/utils/numbers_patch.js index ba9b76a..e2674e8 100644 --- a/static/src/core/utils/numbers_patch.js +++ b/static/src/core/utils/numbers_patch.js @@ -1,56 +1,4 @@ -import { localization } from "@web/core/l10n/localization"; -import { markup } from "@odoo/owl"; - - - -/** - * Wraps the decimal part of a formatted number string in a span for styling. - * Simplified version without inline styles to avoid HTML escaping. - * @param {string} formattedValue - * @returns {import("@odoo/owl").Markup|string} - */ +// Web Decimal Style: wrapDecimal deprecated, now identity function. export function wrapDecimal(formattedValue) { - // Basic validation - if (!formattedValue || typeof formattedValue !== "string") { - return formattedValue; - } - - // If it's already wrapped, don't double wrap - if (formattedValue.includes('class="o_decimal"')) { - return formattedValue; - } - - const decimalPoint = localization.decimalPoint || '.'; - - - - // Handle numbers with decimal points - if (formattedValue.includes(decimalPoint)) { - const parts = formattedValue.split(decimalPoint); - if (parts.length === 2) { - const integerPart = parts[0]; - const decimalPart = parts[1]; - - // Simple regex to separate digits from symbols - const match = decimalPart.match(/^(\d+)(.*)$/); - if (match) { - const digits = match[1]; - const symbols = match[2]; - // Use simple class without inline styles - const result = markup(`${integerPart}${decimalPoint}${digits}${symbols}`); - - return result; - } - } - } - - // Handle whole numbers - force decimal formatting for inventory - if (formattedValue.match(/^\d+$/)) { - const result = markup(`${formattedValue}.000`); - - return result; - } - - return formattedValue; } diff --git a/static/src/css/decimal_style.css b/static/src/css/decimal_style.css index 7374028..188f5a7 100644 --- a/static/src/css/decimal_style.css +++ b/static/src/css/decimal_style.css @@ -1,66 +1,8 @@ -/* Web Decimal Style - Improved readability for better accessibility */ +/* Web Decimal Style - CSS Override Approach */ -/* Base decimal styling - Better contrast for 40+ users */ +/* Base decimal styling */ .o_decimal { - font-size: 0.8em !important; - opacity: 0.85 !important; - display: inline-block !important; - color: #666 !important; - font-weight: 400 !important; - vertical-align: baseline !important; - position: relative !important; -} - -/* Ultra-specific selectors to ensure styling applies */ -html body .o_web_client .o_action_manager .o_action .o_view_controller .o_renderer .o_list_renderer .o_list_table tbody tr td .o_decimal, -html body .o_web_client .o_action_manager .o_action .o_view_controller .o_renderer .o_list_renderer .o_list_table .o_data_row .o_data_cell .o_decimal, -html body .o_web_client .o_action_manager .o_decimal, -html body .o_web_client .o_decimal, -html body .o_decimal, -.o_web_client .o_decimal, -.o_action_manager .o_decimal, -.o_list_table .o_decimal, -.o_field_float .o_decimal, -.o_field_monetary .o_decimal, -.o_list_renderer .o_decimal, -.o_data_row .o_decimal, -.o_data_cell .o_decimal, -td .o_decimal, -div .o_decimal, -span .o_decimal, -table .o_decimal { - font-size: 0.8em !important; - opacity: 0.85 !important; - display: inline-block !important; - color: #666 !important; - font-weight: 400 !important; - vertical-align: baseline !important; - background: none !important; - border: none !important; - margin: 0 !important; - padding: 0 !important; -} - -/* Stock-specific targeting */ -.o_stock_move_line .o_decimal, -.o_stock_move .o_decimal, -[data-model="stock.move.line"] .o_decimal, -[data-model="stock.move"] .o_decimal { - font-size: 0.8em !important; - opacity: 0.85 !important; - color: #666 !important; - font-weight: 400 !important; -} - -/* Force styling on any element with o_decimal class */ -*[class*="o_decimal"] { - font-size: 0.8em !important; - opacity: 0.85 !important; - color: #666 !important; - font-weight: 400 !important; -} - -/* No debug indicator */ -.o_decimal::before { - content: none !important; + font-size: 0.80em !important; + opacity: 0.7 !important; + display: inline-block; } \ No newline at end of file diff --git a/static/src/views/decimal_observer.js b/static/src/views/decimal_observer.js index d67bc69..7e2aa91 100644 --- a/static/src/views/decimal_observer.js +++ b/static/src/views/decimal_observer.js @@ -1,184 +1,117 @@ /** @odoo-module **/ -console.log('Loading ultra-safe decimal observer...'); +import { localization } from "@web/core/l10n/localization"; -// Function to safely apply decimal styling to any element -function safelyApplyDecimalStyling(element) { - if (!element || !element.textContent || !document.contains(element)) return false; +console.log('Web Decimal Style: Loading DOM Decorator observer...'); - // Skip if already processed or if Owl is updating this element - if (element.querySelector('.o_decimal') || - element.classList.contains('o_decimal') || - element.hasAttribute('data-decimal-processed') || - element.hasAttribute('data-owl-updating')) return false; +let timeout; +const processedNodes = new WeakSet(); - // CRITICAL: Skip any editable elements or elements that might become editable - if (element.isContentEditable || - element.closest('.o_field_widget:not(.o_readonly_modifier)') || - element.closest('[contenteditable="true"]') || - element.closest('input') || - element.closest('textarea') || - element.closest('.o_input') || - element.closest('.o_field_float:not(.o_readonly_modifier)') || - element.closest('.o_field_monetary:not(.o_readonly_modifier)') || - element.hasAttribute('contenteditable')) { - return false; - } +function processNode(textNode) { + if (processedNodes.has(textNode)) return; - try { - const text = element.textContent.trim(); - if (!text) return false; + // Safety check: is it still in doc? + if (!document.contains(textNode)) return; - // Mark as processed to avoid conflicts - element.setAttribute('data-decimal-processed', 'true'); + // Check parent + const parent = textNode.parentNode; + if (!parent) return; - // Improved patterns that properly distinguish thousands separators from decimal separators - const patterns = [ - // Currency with decimal: Rp 6,210,000.00 (comma for thousands, dot for decimal) - /^(.*Rp[\s\u00A0]*)(\d[\d,\s\u00A0]*)\.(\d{2})(.*)$/, - // Generic decimal with thousand separators (dot as decimal) - /^(.*?)([\d,\s\u00A0]*\d)\.(\d+)(.*)$/, - // Simple decimal - /^(.*?)(\d+)\.(\d+)(.*)$/ - ]; + // Skip unsafe parents + const tagName = parent.tagName; + if (['SCRIPT', 'STYLE', 'TEXTAREA', 'INPUT', 'OPTION', 'TITLE'].includes(tagName)) return; + if (parent.isContentEditable) return; + if (parent.closest && parent.closest('[contenteditable="true"]')) return; + if (parent.classList.contains('o_decimal')) return; // Already wrapped - for (const pattern of patterns) { - const match = text.match(pattern); - if (match) { - const [, prefix, integerPart, decimalPart, suffix] = match; + const text = textNode.nodeValue; + if (!text || text.length < 3) return; - // console.log('Ultra-Safe Decimal Observer: MATCH FOUND', {text, prefix, integerPart, decimalPart, suffix}); + // Get the correct decimal point from Odoo localization + const decimalPoint = localization.decimalPoint || '.'; + // Escape special regex characters (like dot) + const escapedPoint = decimalPoint.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - // Triple-check the element is safe to modify - // For tfoot, we are more permissive because they are always readonly - if (element.textContent.trim() === text && - document.contains(element) && - (!element.closest('.o_field_widget:not(.o_readonly_modifier)') || element.closest('tfoot'))) { + // STRICT REGEX: (\d)(decimal_point)(\d+) + // We only create a new range if we find a digit, followed by the specific decimal point, followed by digits. + // This strictly avoids matching thousands separators (unless thousands separator == decimal point, which shouldn't happen). - console.log('Ultra-Safe Decimal Observer: STYLING', text, element.tagName, element.className); - const newHTML = `${prefix || ''}${integerPart}.${decimalPart}${suffix || ''}`; - element.innerHTML = newHTML; - return true; - } - } - } + // We match 'g' to find it anywhere, but typically we take the first one. + const regex = new RegExp(`(\\d)(${escapedPoint})(\\d+)`, 'g'); - // Handle whole numbers in quantity contexts (be even more selective) - // Only add decimals to numbers that are clearly quantities in readonly contexts - if (text.match(/^\d+$/) && text.length > 0 && text.length <= 4 && - element.closest('.o_readonly_modifier') && ( - element.closest('[name="quantity"]') || - element.closest('[name="quantity_done"]') || - element.closest('[name="reserved_availability"]') - )) { - console.log('Ultra-Safe Decimal Observer: Adding decimals to readonly quantity', text); + const match = regex.exec(text); + if (match) { + // match[0] = "0.00" + // match[1] = "0" (last int digit) + // match[2] = "." (decimal point) + // match[3] = "00" (decimals) - // Triple-check before updating - if (element.textContent.trim() === text && - document.contains(element) && - element.closest('.o_readonly_modifier')) { - element.innerHTML = `${text}.000`; - return true; - } - } + const lastIntDigit = match[1]; + const decimals = match[3]; - // Do NOT process numbers with commas that don't have decimal points - // These are likely thousands separators (e.g., 8,500 should stay as 8,500) - if (text.match(/^\d{1,3}(?:,\d{3})+$/) && !text.includes('.')) { - console.log('Ultra-Safe Decimal Observer: Skipping thousands separator number', text); - return false; - } + // Split at match start + length of lastIntDigit + const splitIndex = match.index + lastIntDigit.length; - } catch (error) { - console.warn('Ultra-safe decimal styling error (non-critical):', error); - // Remove the processing flag if there was an error - element.removeAttribute('data-decimal-processed'); - } + const middleNode = textNode.splitText(splitIndex); // Starts with decimal point + const endNode = middleNode.splitText(1 + decimals.length); // Rest - return false; -} + // middleNode contains ".00" -// Ultra-safe processing of containers -function ultraSafelyProcessContainer(container) { - if (!container || !document.contains(container)) return; + const span = document.createElement('span'); + span.className = 'o_decimal'; + span.textContent = middleNode.nodeValue; - try { - // Select elements likely to contain formatted decimals in readonly contexts or footers - const elements = container.querySelectorAll('.o_readonly_modifier td:not([data-decimal-processed]), .o_readonly_modifier span:not([data-decimal-processed]), tfoot td:not([data-decimal-processed]), tfoot span:not([data-decimal-processed]), .o_list_number:not([data-decimal-processed])'); - - elements.forEach(element => { - // Optimization: If a TD has a SPAN, we prefer to style the SPAN to preserve tooltips - if (element.tagName === 'TD' && element.querySelector('span')) { - return; - } - - // Only process leaf elements or elements with very simple structures - if ((element.children.length === 0 || - (element.children.length === 1 && element.children[0].tagName === 'SPAN')) && - !element.hasAttribute('data-owl-updating') && - !element.closest('.o_field_widget:not(.o_readonly_modifier)')) { - safelyApplyDecimalStyling(element); - } - }); - } catch (error) { - console.warn('Ultra-safe container processing error (non-critical):', error); - } -} - -// Ultra-conservative observer with longer debounce -const ultraSafeObserver = new MutationObserver((mutations) => { - // Longer debounce to avoid conflicts with user interactions - clearTimeout(ultraSafeObserver.timeout); - ultraSafeObserver.timeout = setTimeout(() => { try { - mutations.forEach((mutation) => { - if (mutation.type === 'childList') { - mutation.addedNodes.forEach((node) => { - if (node.nodeType === Node.ELEMENT_NODE && document.contains(node)) { - // Use longer delay to ensure Owl has finished all updates - setTimeout(() => { - ultraSafelyProcessContainer(node); - }, 500); // Much longer delay - } - }); - } - }); - } catch (error) { - console.warn('Ultra-safe observer error (non-critical):', error); + parent.replaceChild(span, middleNode); + processedNodes.add(textNode); + processedNodes.add(endNode); + processedNodes.add(span.firstChild); + } catch (e) { + console.warn('Web Decimal Style: Failed to replace node', e); } - }, 500); // Longer debounce for 500ms + } +} + + +function scanDocument() { + const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null); + const nodesToProcess = []; + while (walker.nextNode()) { + nodesToProcess.push(walker.currentNode); + } + + for (const node of nodesToProcess) { + processNode(node); + } +} + +function scheduleUpdate() { + if (timeout) cancelAnimationFrame(timeout); + timeout = requestAnimationFrame(scanDocument); +} + +const observer = new MutationObserver((mutations) => { + let shouldUpdate = false; + for (const mutation of mutations) { + if (mutation.type === 'childList' || mutation.type === 'characterData') { + // Avoid reacting to our own changes + if (mutation.target && mutation.target.classList && mutation.target.classList.contains('o_decimal')) continue; + if (mutation.target.parentElement && mutation.target.parentElement.classList.contains('o_decimal')) continue; + + shouldUpdate = true; + } + } + if (shouldUpdate) { + scheduleUpdate(); + } }); -// Start ultra-safe observing -function startUltraSafeObserver() { - // console.log('Ultra-Safe Decimal Observer: Starting ultra-conservative observation'); - - // Process existing content safely with delay - // setTimeout(() => { - // ultraSafelyProcessContainer(document.body); - // }, 1000); // Initial delay to let everything load - - // Start observing for new content with very reduced frequency - // ultraSafeObserver.observe(document.body, { - // childList: true, - // subtree: true - // }); - - // Much less frequent periodic processing to reduce conflicts - // setInterval(() => { - // ultraSafelyProcessContainer(document.body); - // }, 10000); // Every 10 seconds instead of 5 -} - -// Start ultra-safely -/* -if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', () => { - setTimeout(startUltraSafeObserver, 2000); // Extra delay - }); +if (document.body) { + observer.observe(document.body, { childList: true, subtree: true, characterData: true }); + scheduleUpdate(); } else { - setTimeout(startUltraSafeObserver, 2000); // Extra delay -} -*/ - -console.log('Ultra-safe decimal observer disabled'); \ No newline at end of file + document.addEventListener('DOMContentLoaded', () => { + observer.observe(document.body, { childList: true, subtree: true, characterData: true }); + scheduleUpdate(); + }); +} \ No newline at end of file diff --git a/static/src/views/fields/formatters_patch.js b/static/src/views/fields/formatters_patch.js index 6423f4b..0d35cc5 100644 --- a/static/src/views/fields/formatters_patch.js +++ b/static/src/views/fields/formatters_patch.js @@ -1,108 +1,6 @@ -import { registry } from "@web/core/registry"; -import { patch } from "@web/core/utils/patch"; -import { wrapDecimal } from "@web_decimal_style/core/utils/numbers_patch"; -import { MonetaryField } from "@web/views/fields/monetary/monetary_field"; -import { FloatField } from "@web/views/fields/float/float_field"; -import { formatMonetary, formatFloat } from "@web/views/fields/formatters"; - - - -// Safe field patching with error handling -try { - // Patch Components for Form Views - patch(MonetaryField.prototype, { - get formattedValue() { - if (this.props.inputType === "number" && !this.props.readonly && this.value) { - return this.value; - } - const res = formatMonetary(this.value, { - digits: this.currencyDigits, - currencyId: this.currencyId, - noSymbol: !this.props.readonly || this.props.hideSymbol, - }); - - // Start of Owl Safe Decimal Styling - if (this.props.readonly) { - return wrapDecimal(res); - } - // End of Owl Safe Decimal Styling - - return res; - } - }); - - patch(FloatField.prototype, { - get formattedValue() { - if ( - !this.props.formatNumber || - (this.props.inputType === "number" && !this.props.readonly && this.value) - ) { - return this.value; - } - const options = { - digits: this.props.digits, - field: this.props.record.fields[this.props.name], - }; - let res; - if (this.props.humanReadable && !this.state.hasFocus) { - res = formatFloat(this.value, { - ...options, - humanReadable: true, - decimals: this.props.decimals, - }); - } else { - res = formatFloat(this.value, { ...options, humanReadable: false }); - } - - // Start of Owl Safe Decimal Styling - if (this.props.readonly) { - return wrapDecimal(res); - } - // End of Owl Safe Decimal Styling - - return res; - } - }); -} catch (error) { - console.warn('Field patching error (non-critical):', error); -} - -// Safe Registry Patching for List Views -// Safe Registry Patching for List Views -try { - const formattersRegistry = registry.category("formatters"); - - // Store original formatters - const originalFormatters = new Map(); - - function safelyPatchFormatter(name) { - if (formattersRegistry.contains(name) && !originalFormatters.has(name)) { - try { - const original = formattersRegistry.get(name); - originalFormatters.set(name, original); - - formattersRegistry.add(name, (...args) => { - try { - const res = original(...args); - // Safely wrap with Owl Markup - return wrapDecimal(res); - } catch (error) { - console.warn(`Formatter ${name} error (non-critical):`, error); - return original(...args); // Fallback to original - } - }, { force: true }); - - - } catch (error) { - console.warn(`Error patching formatter ${name} (non-critical):`, error); - } - } - } - - // Patch all numeric formatters safely - ['float', 'monetary', 'percentage', 'float_factor', 'float_time'].forEach(safelyPatchFormatter); -} catch (error) { - console.warn('Registry patching error (non-critical):', error); -} +/** @odoo-module **/ + +// Web Decimal Style: Formatters patching disabled in favor of CSS Custom Highlight API. +console.log('Web Decimal Style: Formatters patch disabled.'); diff --git a/static/src/views/inventory_decimal_patch.js b/static/src/views/inventory_decimal_patch.js index 4dc10c3..b00d87f 100644 --- a/static/src/views/inventory_decimal_patch.js +++ b/static/src/views/inventory_decimal_patch.js @@ -1,81 +1,4 @@ /** @odoo-module **/ -import { patch } from "@web/core/utils/patch"; -import { ListRenderer } from "@web/views/list/list_renderer"; - -console.log('Loading inventory decimal patch...'); - -// Safe DOM manipulation approach to avoid Owl lifecycle conflicts -// Safe DOM manipulation approach to avoid Owl lifecycle conflicts -// patch(ListRenderer.prototype, { -// async render() { -// const result = await super.render(); - -// // Schedule decimal styling after Owl completes its rendering cycle -// this.scheduleDecimalStyling(); - -// return result; -// }, - - -// scheduleDecimalStyling() { -// // Use requestAnimationFrame to ensure we run after Owl's DOM updates -// requestAnimationFrame(() => { -// try { -// this.applyDecimalStyling(); -// } catch (error) { -// console.warn('Decimal styling error (non-critical):', error); -// } -// }); -// }, - - -// applyDecimalStyling() { -// if (!this.el || !document.contains(this.el)) return; - -// // Find all cells in the list table, but be more careful about DOM manipulation -// const cells = this.el.querySelectorAll('td:not([data-decimal-processed]), .o_data_cell:not([data-decimal-processed])'); - -// cells.forEach(cell => { -// try { -// // Skip if cell is being updated by Owl -// if (cell.hasAttribute('data-owl-updating')) return; - -// // Mark as processed to avoid double processing -// cell.setAttribute('data-decimal-processed', 'true'); - -// const text = cell.textContent?.trim(); -// if (!text) return; - -// // Check for decimal numbers (including currency) -// const decimalMatch = text.match(/^(.*)(\d+)([.,])(\d+)(.*)$/); -// if (decimalMatch) { -// const [, prefix, integerPart, decimalPoint, decimalPart, suffix] = decimalMatch; - -// console.log('Applying safe DOM decimal styling to:', text); - -// // Create new HTML structure safely -// const newHTML = `${prefix}${integerPart}${decimalPoint}${decimalPart}${suffix}`; - -// // Only update if the content hasn't changed -// if (cell.textContent.trim() === text) { -// // cell.innerHTML = newHTML; -// } -// } -// // Handle whole numbers by adding .000 -// else if (text.match(/^\d+$/) && text.length > 0) { -// console.log('Adding decimals to whole number safely:', text); - -// // Only update if the content hasn't changed -// if (cell.textContent.trim() === text) { -// // cell.innerHTML = `${text}.000`; -// } -// } -// } catch (error) { -// console.warn('Error processing cell (non-critical):', error); -// } -// }); -// } -// }); - -console.log('Inventory decimal patch loaded'); \ No newline at end of file +// Web Decimal Style: Inventory decimal patch disabled in favor of CSS Custom Highlight API. +console.log('Web Decimal Style: Inventory decimal patch disabled.'); \ No newline at end of file diff --git a/static/src/views/purchase_dashboard_patch.js b/static/src/views/purchase_dashboard_patch.js index 69bc2a9..c11a6f1 100644 --- a/static/src/views/purchase_dashboard_patch.js +++ b/static/src/views/purchase_dashboard_patch.js @@ -1,11 +1,4 @@ /** @odoo-module **/ -import { PurchaseDashBoard } from "@purchase/views/purchase_dashboard"; -import { patch } from "@web/core/utils/patch"; -import { wrapDecimal } from "@web_decimal_style/core/utils/numbers_patch"; - -patch(PurchaseDashBoard.prototype, { - formatDecimal(value) { - return wrapDecimal(value); - } -}); +// Web Decimal Style: Purchase dashboard patch disabled in favor of CSS Custom Highlight API. +console.log('Web Decimal Style: Purchase dashboard patch disabled.'); diff --git a/static/src/views/tax_totals_patch.js b/static/src/views/tax_totals_patch.js index 2df436a..f0cb77a 100644 --- a/static/src/views/tax_totals_patch.js +++ b/static/src/views/tax_totals_patch.js @@ -1,32 +1,6 @@ /** @odoo-module **/ -import { patch } from "@web/core/utils/patch"; -import { wrapDecimal } from "@web_decimal_style/core/utils/numbers_patch"; -import { TaxTotalsComponent } from "@account/components/tax_totals/tax_totals"; - - - -// Patch TaxTotalsComponent (the main widget) -patch(TaxTotalsComponent.prototype, { - formatMonetary(value) { - const result = super.formatMonetary(value); - return wrapDecimal(result); - } -}); - -// We also need to patch TaxGroupComponent which is a sub-component defined in the same file -// However, it's not exported directly in Odoo 16/17/18/19 usually, but accessible via TaxTotalsComponent.components -if (TaxTotalsComponent.components && TaxTotalsComponent.components.TaxGroupComponent) { - const TaxGroupComponent = TaxTotalsComponent.components.TaxGroupComponent; - - patch(TaxGroupComponent.prototype, { - formatMonetary(value) { - const result = super.formatMonetary(value); - return wrapDecimal(result); - } - }); -} else { - console.warn('Web Decimal Style: Could not find TaxGroupComponent to patch'); -} +// Web Decimal Style: Tax totals patch disabled in favor of CSS Custom Highlight API. +console.log('Web Decimal Style: Tax totals patch disabled.');