Uploaded image for project: 'Blesta Core'
  1. Blesta Core
  2. CORE-5590

Unit price formated incorrectly on invoices for some currency formats

    Details

    • Type: Bug
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: 5.13.0-b2
    • Component/s: None
    • Labels:
      None

      Description

      Credits to BW on discord for bringing to our attention

      To reproduce

      • update a currency to use a format with a comma decimal separator (ex. 1234,56)
      • create an invoice with that currency, unit price anything but lets say 4
      • download the invoice and see the unit price column shows 4,0000.00

      To resolve, in app/models/currencies.php around line 400 replace

      
              
              // Format the currency
              switch ($formats[$currency][$company_id]->format) {
                  // Values with decimal separator
                  case '#,###.##':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, '.', $with_separator ? ',' : ''),
                          $decimals,
                          '.'
                      );
                      break;
                  case '#.###,##':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, ',', $with_separator ? '.' : ''),
                          $decimals,
                          ','
                      );
                      break;
                  case '# ###.##':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, '.', $with_separator ? ' ' : ''),
                          $decimals,
                          '.'
                      );
                      break;
                  case '# ###,##':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, ',', $with_separator ? ' ' : ''),
                          $decimals,
                          ','
                      );
                      break;
                  case '#,##,###.##':
                      $value = number_format($value, $decimals, '.', '');
                      // If value over 1000 need to format specially
                      if ($with_separator && $value >= 1000) {
                          $thousandths_length = strlen($value) - ($decimals + 2);
                          $temp_val = $value;
                          $value = substr($temp_val, -($decimals + 1)); // hold decimals
                          // format value
                          for ($j = 0, $i = $thousandths_length; $i >= 0; $i--, $j++) {
                              // Thousandths place
                              if ($j < 3) {
                                  $value = $temp_val[$i] . $value;
                              } else {
                                  // All others
                                  $value = $temp_val[$i] . (($j + 3) % 2 == 0 ? ',' : '') . $value;
                              }
                          }
                      }
                      $value = $this->truncateDecimal($value, $decimals, '.');
                      break;
                  // Values with no decimal separator (unless explicitly given)
                  case '# ###':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, '.', $with_separator ? ' ' : ''),
                          $decimals,
                          '.'
                      );
                      break;
                  case '#.###':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, ',', $with_separator ? '.' : ''),
                          $decimals,
                          ','
                      );
                      break;
                  case '#,###':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, '.', $with_separator ? ',' : ''),
                          $decimals,
                          '.'
                      );
                      break;
                  case '####.##':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, '.', ''),
                          $decimals,
                          '.'
                      );
                      break;
                  case '####,##':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, ',', ''),
                          $decimals,
                          ','
                      );
                      break;
                  default:
                      return $value; // format was unrecognized, return the value as-is
              }
      
              // Remove non-significant decimals
              if ($significant_decimals) {
                  $value = preg_replace('/(\.[0-9]+?)0*$/', '$1', $value);
      
                  // Force at leas 2 decimals
                  if (strpos($value, '.') === false) {
                      $value .= '.00';
                  } else {
                      $decimals = strlen(substr(strrchr($value, '.'), 1));
                      if ($decimals < 2) {
                          $value .= str_repeat('0', 2 - $decimals);
                      }
                  }
              }
      

      With

      
              // Format the currency
              $decimal_separator = '.';
              switch ($formats[$currency][$company_id]->format) {
                  // Values with decimal separator
                  case '#,###.##':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, '.', $with_separator ? ',' : ''),
                          $decimals,
                          '.'
                      );
                      break;
                  case '#.###,##':
                      $decimal_separator = ',';
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, ',', $with_separator ? '.' : ''),
                          $decimals,
                          ','
                      );
                      break;
                  case '# ###.##':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, '.', $with_separator ? ' ' : ''),
                          $decimals,
                          '.'
                      );
                      break;
                  case '# ###,##':
                      $decimal_separator = ',';
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, ',', $with_separator ? ' ' : ''),
                          $decimals,
                          ','
                      );
                      break;
                  case '#,##,###.##':
                      $value = number_format($value, $decimals, '.', '');
                      // If value over 1000 need to format specially
                      if ($with_separator && $value >= 1000) {
                          $thousandths_length = strlen($value) - ($decimals + 2);
                          $temp_val = $value;
                          $value = substr($temp_val, -($decimals + 1)); // hold decimals
                          // format value
                          for ($j = 0, $i = $thousandths_length; $i >= 0; $i--, $j++) {
                              // Thousandths place
                              if ($j < 3) {
                                  $value = $temp_val[$i] . $value;
                              } else {
                                  // All others
                                  $value = $temp_val[$i] . (($j + 3) % 2 == 0 ? ',' : '') . $value;
                              }
                          }
                      }
                      $value = $this->truncateDecimal($value, $decimals, '.');
                      break;
                  // Values with no decimal separator (unless explicitly given)
                  case '# ###':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, '.', $with_separator ? ' ' : ''),
                          $decimals,
                          '.'
                      );
                      break;
                  case '#.###':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, ',', $with_separator ? '.' : ''),
                          $decimals,
                          ','
                      );
                      break;
                  case '#,###':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, '.', $with_separator ? ',' : ''),
                          $decimals,
                          '.'
                      );
                      break;
                  case '####.##':
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, '.', ''),
                          $decimals,
                          '.'
                      );
                      break;
                  case '####,##':
                      $decimal_separator = ',';
                      $value = $this->truncateDecimal(
                          number_format($value, $decimals, ',', ''),
                          $decimals,
                          ','
                      );
                      break;
                  default:
                      return $value; // format was unrecognized, return the value as-is
              }
      
              // Remove non-significant decimals
              if ($significant_decimals) {
                  $value = preg_replace('/(\\' . $decimal_separator . '[0-9]+?)0*$/', '$1', $value);
      
                  // Force at leas 2 decimals
                  if (strpos($value, $decimal_separator) === false) {
                      $value .= $decimal_separator . '00';
                  } else {
                      $decimals = strlen(substr(strrchr($value, $decimal_separator), 1));
                      if ($decimals < 2) {
                          $value .= str_repeat('0', 2 - $decimals);
                      }
                  }
              }
      

        Activity

        There are no comments yet on this issue.

          People

          • Assignee:
            Unassigned
            Reporter:
            jonathan Jonathan Reissmueller
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: