Skip to content

Fix niels: sales by year#1325

Closed
nielsdrost7 wants to merge 10 commits intodevelopmentfrom
fix/niels-1-sales-by-year
Closed

Fix niels: sales by year#1325
nielsdrost7 wants to merge 10 commits intodevelopmentfrom
fix/niels-1-sales-by-year

Conversation

@nielsdrost7
Copy link
Copy Markdown
Contributor

@nielsdrost7 nielsdrost7 commented Aug 21, 2025

Fix niels: sales by year

Summary by CodeRabbit

  • Bug Fixes
    • Report filters now correctly apply minimum and maximum quantity values, preventing inaccurate or inconsistent results.
    • Date range defaults behave consistently when no dates are provided, avoiding unexpected filtering.
    • Filters now handle numeric quantity inputs more robustly across tax-inclusive and tax-exclusive report views.
    • Reduced edge-case failures by enforcing numeric safety in quantity comparisons.

@nielsdrost7 nielsdrost7 requested a review from Copilot September 5, 2025 05:32

This comment was marked as outdated.

@nielsdrost7 nielsdrost7 requested a review from Copilot September 5, 2025 09:02

This comment was marked as outdated.

nielsdrost7 and others added 4 commits September 7, 2025 06:00
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

This comment was marked as outdated.

nielsdrost7 and others added 2 commits September 7, 2025 08:10
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@nielsdrost7 nielsdrost7 requested a review from Copilot September 7, 2025 06:11
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes SQL injection vulnerabilities in the sales_by_year report function by properly escaping user input parameters and simplifying quantity validation logic.

  • Replaces conditional quantity validation with direct integer casting
  • Adds proper database escaping for minQuantity and maxQuantity parameters in SQL queries
  • Removes unnecessary empty line spacing

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread application/modules/reports/models/Mdl_reports.php Outdated
@naui95 naui95 added this to the 1.6.4 milestone Sep 7, 2025
@nielsdrost7 nielsdrost7 requested a review from Copilot October 5, 2025 11:57
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +214 to +215
$minQuantity = (int) $minQuantity;
$maxQuantity = (int) $maxQuantity;
Copy link

Copilot AI Oct 5, 2025

Choose a reason for hiding this comment

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

Casting $maxQuantity (default null) to 0 when it is not provided changes behavior from (previously invalid SQL that should have been omitted) to a restrictive filter (0 >= SUM(...)) that will likely exclude all valid rows. Instead, only apply the max quantity predicate when a max value is explicitly supplied (e.g., not null / not empty), leaving the upper bound unbounded otherwise.

Copilot uses AI. Check for mistakes.
Comment thread application/modules/reports/models/Mdl_reports.php Outdated
nielsdrost7 and others added 2 commits October 5, 2025 14:00
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Oct 5, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Updates Mdl_reports.php to cast quantity filters to integers, escape values in SQL WHERE clauses, and standardize from_date/to_date handling via direct ternary date_to_mysql conversions. Control flow remains the same for taxChecked branches; only type handling and SQL fragment construction are adjusted.

Changes

Cohort / File(s) Summary
Reports model sanitization
application/modules/reports/models/Mdl_reports.php
Casts minQuantity/maxQuantity to ints; replaces empty-string checks with ternary date_to_mysql for from_date/to_date; updates SQL WHERE construction to use explicit integer casting and $this->db->escape(...) for quantity comparisons; preserves existing branch logic for taxChecked states.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

A twitch of whiskers, tidy and neat,
I cast my numbers—none shall cheat.
Dates hop clean through MySQL’s gate,
WHERE clauses sip from sanitized plate.
Burrow secure, reports run bright—
Carrots counted, type-safe delight. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The pull request title “Fix niels: sales by year” does not convey the actual changes, which center on normalizing date defaults and enforcing integer casting for quantity filters in the Mdl_reports model, and it includes a personal reference that offers no technical detail. The lack of specificity makes it unclear to a reviewer what the PR addresses. Therefore the title is misleading and too broad. Rename the pull request to clearly reflect the key changes, for example “Normalize report date defaults and enforce integer quantity filters in Mdl_reports.php,” removing personal references and focusing on the technical update.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/niels-1-sales-by-year

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
application/modules/reports/models/Mdl_reports.php (1)

326-326: Handle null quantity values in WHERE clause.

After fixing the casting issue at lines 214-215, these lines need null checks to avoid injecting null into the SQL (which would cause syntax errors).

Apply this diff to conditionally include the quantity filters:

-                                    AND ' . $minQuantity . ' <=
+                                    AND ' . ($minQuantity !== null ? $minQuantity : 0) . ' <=
                                     (
                                         SELECT SUM(amounts2.invoice_item_subtotal) FROM ip_invoice_amounts amounts2
                                             WHERE amounts2.invoice_id IN
                                             (
                                                 SELECT inv2.invoice_id FROM ip_invoices inv2
                                                     WHERE inv2.client_id=ip_clients.client_id
                                                         AND ' . $this->db->escape($from_date) . ' <= inv2.invoice_date_created
                                                         AND ' . $this->db->escape($to_date) . ' >= inv2.invoice_date_created
                                             )
-                                    ) AND ' . $maxQuantity . ' >=
+                                    )' . ($maxQuantity !== null ? ' AND ' . $maxQuantity . ' >=' : ' AND 1=1 OR 0 >=') . '

Better yet, refactor to only add these clauses when values are provided (see the conditional logic at line 228 for if ($maxQuantity)).

Also applies to: 336-336

♻️ Duplicate comments (4)
application/modules/reports/models/Mdl_reports.php (4)

449-449: Handle null minQuantity value in WHERE clause.

Same issue as lines 326, 336: after fixing the casting at line 214, this needs a null check.

Apply this diff:

-                                    AND ' . $minQuantity . ' <=
+                                    AND ' . ($minQuantity !== null ? $minQuantity : 0) . ' <=

214-215: Critical: Casting null to 0 breaks max quantity logic.

Casting $maxQuantity (default null) to 0 transforms an intended unbounded filter into a highly restrictive one (0 >= SUM(...)) that excludes all positive totals. When no max is provided, the upper-bound check should be omitted entirely.

Apply this diff to only cast when values are actually provided:

-        $minQuantity = (int) $minQuantity;
-        $maxQuantity = (int) $maxQuantity;
+        $minQuantity = $minQuantity !== null && $minQuantity !== '' ? (int) $minQuantity : null;
+        $maxQuantity = $maxQuantity !== null && $maxQuantity !== '' ? (int) $maxQuantity : null;

Then check for null before using these values in WHERE clauses (see subsequent comments).


564-564: Inconsistent quantity handling: mixing inline cast with escape.

Line 564 uses (int)$minQuantity while line 574 uses $this->db->escape($maxQuantity). Since both are already cast to integers at lines 214-215, this inconsistency is confusing.

Choose one approach and apply consistently:

Option 1: Direct integer concatenation (preferred after fixing null handling):

-                                    AND ' . (int)$minQuantity . ' <=
+                                    AND ' . ($minQuantity !== null ? $minQuantity : 0) . ' <=
                                     (
                                         SELECT SUM(amounts2.invoice_total) FROM ip_invoice_amounts amounts2
                                             WHERE amounts2.invoice_id IN
                                             (
                                                 SELECT inv2.invoice_id FROM ip_invoices inv2
                                                     WHERE inv2.client_id=ip_clients.client_id
                                                         AND ' . $this->db->escape($from_date) . ' <= inv2.invoice_date_created
                                                         AND ' . $this->db->escape($to_date) . ' >= inv2.invoice_date_created
                                             )
-                                    ) AND ' . $this->db->escape($maxQuantity) . ' >=
+                                    )' . ($maxQuantity !== null ? ' AND ' . $maxQuantity . ' >=' : ' AND 1=1 OR 0 >=') . '

Option 2: Use escape consistently (if you prefer belt-and-suspenders):

-                                    AND ' . (int)$minQuantity . ' <=
+                                    AND ' . $this->db->escape($minQuantity !== null ? $minQuantity : 0) . ' <=

Also applies to: 574-574


687-687: Inconsistent with line 564 and needs null handling.

Line 564 uses (int)$minQuantity while this line uses $this->db->escape($minQuantity). Pick one approach and apply it consistently across all WHERE clauses.

After fixing the casting at line 214 to allow null values, update this line:

-                                    AND ' . $this->db->escape($minQuantity) . ' <=
+                                    AND ' . ($minQuantity !== null ? $minQuantity : 0) . ' <=

Or use escape consistently:

-                                    AND ' . $this->db->escape($minQuantity) . ' <=
+                                    AND ' . $this->db->escape($minQuantity !== null ? $minQuantity : 0) . ' <=
🧹 Nitpick comments (1)
application/modules/reports/models/Mdl_reports.php (1)

217-218: Validate date conversion results.

date_to_mysql() returns an empty string if the date format is invalid. Using that empty string directly in SQL comparisons could produce unexpected results.

Consider validating the conversion result:

-        $from_date      = $from_date == '' ? date('Y-m-d') : date_to_mysql($from_date);
-        $to_date        = $to_date   == '' ? date('Y-m-d') : date_to_mysql($to_date);
+        $from_date      = $from_date == '' ? date('Y-m-d') : date_to_mysql($from_date);
+        $to_date        = $to_date   == '' ? date('Y-m-d') : date_to_mysql($to_date);
+        
+        // Fallback to today if conversion fails
+        $from_date = $from_date ?: date('Y-m-d');
+        $to_date   = $to_date   ?: date('Y-m-d');
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9dff57e and 9b90780.

📒 Files selected for processing (1)
  • application/modules/reports/models/Mdl_reports.php (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
application/modules/reports/models/Mdl_reports.php (1)
application/helpers/date_helper.php (1)
  • date_to_mysql (120-126)

@nielsdrost7
Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Oct 12, 2025

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
application/modules/reports/models/Mdl_reports.php (2)

326-336: Standardize quantity interpolation across all branches.

The code uses three different patterns for inserting integer quantities into SQL:

  • Lines 326, 336, 449: direct concatenation (no cast, no escape)
  • Line 564: inline (int) cast
  • Lines 574, 687: escape() calls

Since quantities are already cast to int at line 214-215, choose one consistent approach—either direct concatenation or inline casting—and apply it uniformly.

-                                    AND ' . $minQuantity . ' <=
+                                    AND ' . (int)$minQuantity . ' <=
 (...)
-                                    ) AND ' . $maxQuantity . ' >=
+                                    ) AND ' . (int)$maxQuantity . ' >=

Then update lines 449, 564, 574, 687 similarly for uniformity.

Based on past review comments.


214-215: Critical: Casting null $maxQuantity to 0 breaks unbounded filtering.

Casting $maxQuantity (default null) to (int) yields 0, which changes the filter from "no upper limit" to "exclude rows where SUM(...) > 0"—effectively blocking all valid results when the user does not specify a max.

Solution: Only apply the max-quantity predicate when a non-null, non-zero value is explicitly provided.

Apply this diff to conditionally apply the max filter:

-        $minQuantity = (int) $minQuantity;
-        $maxQuantity = (int) $maxQuantity;
+        $minQuantity = $minQuantity !== null && $minQuantity !== '' ? (int) $minQuantity : 0;
+        $maxQuantity = $maxQuantity !== null && $maxQuantity !== '' ? (int) $maxQuantity : null;

Then, in the WHERE clauses (lines 326-348, 449-461, 555-586, 678-699), wrap the max-quantity comparison in a conditional check:

 AND ' . $minQuantity . ' <=
 (...)
-) AND ' . $maxQuantity . ' >=
+)' . ($maxQuantity !== null ? ' AND ' . $maxQuantity . ' >=' : '') . '
 (...)

Based on learnings and past review comments.

🧹 Nitpick comments (1)
application/modules/reports/models/Mdl_reports.php (1)

217-218: Consider null-safe date handling.

The empty-string check (== '') may not catch all cases where dates are unset. For more robust validation, check for null or empty().

-        $from_date      = $from_date == '' ? date('Y-m-d') : date_to_mysql($from_date);
-        $to_date        = $to_date   == '' ? date('Y-m-d') : date_to_mysql($to_date);
+        $from_date      = empty($from_date) ? date('Y-m-d') : date_to_mysql($from_date);
+        $to_date        = empty($to_date)   ? date('Y-m-d') : date_to_mysql($to_date);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9dff57e and 9b90780.

📒 Files selected for processing (1)
  • application/modules/reports/models/Mdl_reports.php (4 hunks)

@nielsdrost7
Copy link
Copy Markdown
Contributor Author

closing this one, this one was merged when i merged #1354

@nielsdrost7 nielsdrost7 deleted the fix/niels-1-sales-by-year branch January 20, 2026 08:47
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.

3 participants