I have a small script that generates quotes. I can add items with related discount or tax values, however the calculation does not seem to be correct as it's not subtracting the discount value. Based upon the screenshot I will attach the item subtotal should amount to 155,584.00
Please refer to my script below as well as a screenshot
foreach ($items as $item) {
$itemSubTotal = $item['quantity'] * $item['unit_price'];
$discount_rate=$item['discount_rate'];
$unit_price=$item['unit_price'];
$subTotal += $itemSubTotal;
$itemDiscount=$itemSubTotal*$discount_rate/100;
$discount+=$itemDiscount;
$itemTax = $itemSubTotal * ($item['tax_rate'] / 100);
$tax += $itemTax;
$itemSubTotal = number_format($itemSubTotal, 2, '.', ',');
$y+=5;
$pdf->setXY(5, $y);
$pdf->MultiCell(10, 5, $i++, 0, 'L');
$pdf->setXY(15, $y);
$pdf->Cell(30, 5, $item['title'], 0, 2, 'L');
$pdf->setXY(45, $y);
$pdf->Cell(30, 5, $item['details'], 0, 2, 'L');
$pdf->setXY(125, $y);
$pdf->MultiCell(20, 5, $item['quantity'], 0, 'R');
$pdf->setXY(145, $y);
$pdf->MultiCell(15, 5, number_format($unit_price, 2, '.', ','), 0, 'R');
$pdf->setXY(160, $y);
$pdf->MultiCell(20, 5, number_format($discount_rate, 2, '.', ','), 0, 'R');
$pdf->setXY(180, $y);
$pdf->MultiCell(25, 5, $itemSubTotal, 0, 'R');
How can I get this fixed? Some expert advise would be greatly appreciated
You haven't modified the $itemSubTotal variable with the discount. you should do this before printing it:
$itemSubTotal = $itemSubTotal*($discount_rate/100);
also, according to my calculation, the item subtotal would be 83,776.00
Related
I am trying to print some words in a cell but wordwrap in not working in a cell, what should i do?
$pdf->setXY(124, 36 + ($i * 5.1));
$pdf->SetFillColor(238, 236, 225);
$pdf->SetFont('Arial', '', 8);
$pdf->Cell(40, 6, $resultArrayIndex['pubtitle'], 0, 0, 'L', True);
Here is my output -
and here what i am trying to achieve - trying to wrap word within a cell. (Any help or hint is appreciated)
Edited after comments and sugggestions
After all u suggesting me use Multicell, I used it but it's still not helpful
not equal gap with each multicell and even sometimes it's uneven size text and gap
My code after your suggestion and i am using it in for-loop
$pdf->setXY(17, 36+($i * 6.9));
$pdf->SetFillColor(255,255,255);
$pdf->SetFont('Arial', '', 8);
$pdf->MultiCell(19, 4.6, formatPubDate($resultArrayIndex['pubdate']), 1);
$pdf->setXY(42, 36 + ($i * 6.9));
$pdf->SetFont('Arial', '', 8);
$pdf->MultiCell(50.5, 4.6, ($resultArrayIndex['title']), 1);
$pdf->setXY(124, 33.7 + ($i * 9.0));
$pdf->SetFont('Arial', '', 8);
$pdf-> MultiCell(27, 2.9 , $resultArrayIndex['pubtitle'],1);
I have a small script created in CakePHP where I can generate quotes, however the quote items seem to be sorted in a non specific way on my PDF. What is the best way to have this sorted by ID in an ascending order ?
Find below my related code snippet which will list all items on my quote:
foreach ($items as $item) {
$itemSubTotal = $item['quantity'] * $item['unit_price'];
$discount_rate=$item['discount_rate'];
$unit_price=$item['unit_price'];
$subTotal += $itemSubTotal;
$itemDiscount=$itemSubTotal*$discount_rate/100;
$discount+=$itemDiscount;
//$itemTax = $itemSubTotal * ($item['tax_rate'] / 100);
$itemTax = ($itemSubTotal - $itemDiscount) * ($item['tax_rate'] / 100);
$tax += $itemTax;
$itemSubTotal = $itemSubTotal*((100-$discount_rate) / 100);
$itemSubTotal = number_format($itemSubTotal, 2, '.', ',');
$y+=5;
$pdf->setXY(5, $y);
$pdf->MultiCell(10, 5, $i++, 0, 'L');
$pdf->setXY(15, $y);
//$pdf->MultiCell(30, 5, $item['title'], 0, 'L');
$pdf->Cell(30, 5, $item['title'], 0, 2, 'L');
$pdf->setXY(45, $y);
//$pdf->MultiCell(80, 5, $item['details'], 0, 'L');
$pdf->Cell(30, 5, $item['details'], 0, 2, 'L');
$pdf->setXY(125, $y);
$pdf->MultiCell(20, 5, $item['quantity'], 0, 'R');
$pdf->setXY(145, $y);
$pdf->MultiCell(15, 5, number_format($unit_price, 2, '.', ','), 0, 'R');
$pdf->setXY(160, $y);
$pdf->MultiCell(20, 5, number_format($discount_rate, 2, '.', ','), 0, 'R');
$pdf->setXY(180, $y);
$pdf->MultiCell(25, 5, $itemSubTotal, 0, 'R');
}
Some expert help would be greatly appreciated, thank you
I have not tried this, but it should work. Have a look at cake 3 collections and specifically sortBy
If you wrap your $items in a collection, then sort them, then iterate through them you will achieve your goal.
Something like:
use Cake\Collection\Collection;
$collection = new Collection($items);
$sortedByField = $collection->sortBy('field')
If this doesn't work have a play with the other methods like groupBy
First of all i am really sorry for my english. I try to explain my wanted. I use fpdf to make dynamic invoice in pdf. I have more than one product to add one invoice and i must list them sub-bottom. But products counts change in all invoices. Some invoice has 5 products but some invoice has 2 products. My problem is i use code below but all lines overrided.
$invoices_query = mysql_query("SELECT * FROM invoice_bookings WHERE invoice_code = '$invoice_code'");
while ($invoices = mysql_fetch_array($invoices_query)) {
$customers_name = $invoices['customer_name'];
$pdf->Ln(0);
$pdf->Cell(21,123,$invoice_number,0,0,'L',0); // empty cell with left,top, and right borders
$pdf->Cell(30,123,$customers_name,0,0,'L',0);
$pdf->Cell(20,123,$date,0,0,'L',0);
$pdf->Cell(20,123,$time,0,0,'L',0);
$pdf->Cell(30,123,$suburb_from,0,0,'L',0);
$pdf->Cell(34,123,$suburb_to,0,0,'L',0);
$pdf->Cell(10,123,'% ' . $tax_percent,0,0,'L',0);
$pdf->Cell(25,123,'$ ' . $invoice_price,0,0,'R',0);
}
You can see value of margin. It's 123 as you can see. I must increase this value to 132 for example. And for other product 142 i must make. For example there are 5 products in this invoice i must make like this ;
first 123
second 133
third 143
fourth 153
fifth 163
but i really don't know how can i do this.
As this. Add a counter, initialize it, and always incrase with 10.
$cnt = 123; //Init the counter
while ($invoices = mysql_fetch_array($invoices_query)) {
$customers_name = $invoices['customer_name'];
$pdf->Ln(0);
$pdf->Cell(21, $cnt, $invoice_number, 0, 0, 'L', 0); // empty cell with left,top, and right borders
$pdf->Cell(30, $cnt, $customers_name, 0, 0, 'L', 0);
$pdf->Cell(20, $cnt, $date, 0, 0, 'L', 0);
$pdf->Cell(20, $cnt, $time, 0, 0, 'L', 0);
$pdf->Cell(30, $cnt, $suburb_from, 0, 0, 'L', 0);
$pdf->Cell(34, $cnt, $suburb_to, 0, 0, 'L', 0);
$pdf->Cell(10, $cnt, '% ' . $tax_percent, 0, 0, 'L', 0);
$pdf->Cell(25, $cnt, '$ ' . $invoice_price, 0, 0, 'R', 0);
$cnt = $cnt + 10; //Incrase it in the loop.
}
NOTE
Do not use mysql functions, they are deprecated. Use mysqli or PDO instead.
Avoid sql injections by escaping your variables comes from outside, or use prepared statements.
I'm trying to put multicolor text through imagettftext.
I tried drawing letter by letter but the spacing is horrible.
Here's my code:
$usrname_split = str_split("MarioErmando");
$onecharwidth = imagefontwidth((int)$font)*(12/8);
foreach($usrname_split as $key=>$letter){
if($key == 0){
// first letter
imagettftext($im, 12, 0, $xusrname, 15, $blue, $font, $letter);
$oldletters = "$letter";
}else{
$posarr=imageftbbox(12, 0 ,$font, $oldletters);
$posx = $posarr["2"];
imagefttext($im, 12, 0, $posx, 15, $red, $font, $letter);
$oldletters .= "$letter";
}
}
The output:
Note that the text is dynamic.
Is it possible to achieve multicolor text through imagettftext without horrible spacing?
Regards, MarioErmando.
in order to test, replace your code by this one:
$string="Mario Ermando";
$last_string= substr( $string, 1 );
imagettftext($im, 12, 0, $xusrname, 20, $blue, $font, $string[0]); //first letter "M"
imagefttext($im, 12, 0, 12, 20, $red, $font, $last_string);
i think the problem is when you write every letter separately
I have an array of numbers and the ammount of properties in the array cannot be determined.
example:
array(30, 30, 10, 20, 60);
array(2, 53, 71, 22);
array(88, 22, 8);
etc...
Now normally, the sum of all the array values will be 100 or less.
What I want to do is, when they are over 100, reduce them all to make it equal to 100. Normally i would just divide the difference and then take away but for example, the first array adds up to 150, and if I divide the difference (50) evenly, i would end up with:
array(20, 20, 0, 10, 50);
But i want the numbers to be subtracted according to their size, so 30 would have a larger chunk taken out then 10.
The way I would do it is divide each value by (total_sum / 100), and that works perfectly. Now what I need to do is be able to select one value which becomes dominant and cannot be subtracted from then subtract all other values until sum is 100. Example below:
array(20, 20, 80); // 80 is the dominant number
After normalising, the array would be:
array(10, 10, 80);
Example 2:
array(20, 20, 40, 60); // 40 is dominant number
after normalising:
array(10, 10, 40, 20) // maybe it wouldnt be those exact values bhut just to show how different size numbers get reduced according to size. But now total sum is 100
Example 3:
array(23, 43, 100, 32) // 100 is dominant
normalise
array(0, 0, 100, 0);
I have tried so many things but nothing seems to work. How would i accomplish this?
Thanks
If I understand your problem correctly, you're just about done. Just remove the dominant value from your input array, reduce the 100 by that value, and do the rest like before:
function helper($values, $sum) {
$f = array_sum($values) / $sum;
return array_map(function ($v) use($f) {
return $v / $f;
}, $values);
}
// input
$a = array(20, 20, 40, 60);
// remove the dominant value (index: 2)
$b = array_splice($a, 2, 1);
// `normalize` the remaining values using `100 - dominant value` instead of `100`
$c = helper($a, 100 - $b[0]);
// re-inject the dominant value
array_splice($c, 2, 0, $b);
// output
print_r($c); // => [12, 12, 40, 36]
Try this?
function normalise_array($array_to_work_on,$upper_limit){
$current_total = array_sum($array_to_work_on);
$reduce_total_by = $current_total - $upper_limit;
$percentage_to_reduce_by = floor(($reduce_total_by / $current_total) * 100);
$i = 0;
$new_array;
foreach($array_to_work_on as $item){
$reduce = ($item / 100) * $percentage_to_reduce_by;
$new_array[$i] = floor($item - $reduce);
$i ++;
echo $new_array[$i];
}
return($new_array);
}
$numbers1 = array(30, 30, 10, 20, 89);
print_r(normalise_array($numbers1,20));
echo "<br />";
echo "<br />First array total: ".array_sum(normalise_array($numbers1,20));
echo "<br /><br/ >";
$numbers2 = array(234, 30, 10, 20, 60);
print_r(normalise_array($numbers2,100));
echo "<br />First array total: ".array_sum(normalise_array($numbers2,100));