Auto increment Invoice ID in Code-igniter - php

i am very new to code igniter /php .
Before i was using randomly generated invoice number like
$invoice_no = rand(9999,9999999999);
But now i wanted to increment invoice number and add current year as a prefix to it . But somewhere i am doing wrong as this code failed execute . Can some one point me in the right direction .
My model is ...
function insertInvoice($data)
{
$this->db->trans_begin();
$invoice = array();
if(!empty($data['client_id']))
{
$invoice['invoice_client_id'] = $data['client_id'];
}else{
$client_data = array(
'client_name' => $data['customername'],
'client_address1' => $data['address1']
);
$this->db->insert('client_details', $client_data);
$insert_id = $this->db->insert_id();
$invoice['invoice_client_id'] = $insert_id;
}
$query = $this->db->query("SELECT * FROM invoice ORDER BY invoice_id DESC LIMIT 1");
$result = $query->result_array(0);
$result ++;
$curYear = date('Y');
$invoice_no = $curYear . '-' .$result;
$invoice['invoice_no'] = $invoice_no;
$invoice['invoice_subtotal'] = $data['subTotal'];
$invoice['invoice_tax'] = $data['tax'];
$invoice['invoice_tax_amount'] = $data['taxAmount'];
$invoice['invoice_total'] = $data['totalAftertax'];
$invoice['invoice_total_extra'] = $data['totalextra'];
$invoice['invoice_rent'] = $data['rent'];
$invoice['invoice_paid'] = $data['amountPaid'];
$invoice['invoice_due'] = $data['amountDue'];
$invoice['invoice_desc'] = $data['notes'];
$invoice['invoice_items_count'] = $data['item_count'];
$invoice['invoice_extra_count'] = $data['extra_count'];
$invoice['invoice_miscellaneous'] = $data['miscellaneous'];
$this->db->insert('invoice', $invoice);
$i=1;
do {
$items = array(
'invoice_no' => $invoice_no,
'item_name' => $data['invoice']['product_name'][$i],
'item_price' => $data['invoice']['product_price'][$i],
'item_qty' => $data['invoice']['product_qty'][$i],
'item_total' => $data['invoice']['total'][$i],
'item_noof_crate_wait' => $data['invoice']['noof_crate_wait'][$i],
'item_crate_wait' => $data['invoice']['crate_wait'][$i],
'item_choot' => $data['invoice']['choot'][$i],
'item_net_quantity' => $data['invoice']['net_qty'][$i]
);
$this->db->insert('invoice_items',$items);
$i++;
} while($i<$data['item_count']);
$j=1;
do {
$extraitems = array(
'invoice_no' => $invoice_no,
'extra_item_name' => $data['extra']['name'][$j],
'extra_item_qunatity' => $data['extra']['qty'][$j],
'extra_item_price' => $data['extra']['price'][$j],
'extra_item_total' => $data['extra']['total'][$j]
);
$this->db->insert('extra_items',$extraitems);
$j++;
} while($j<$data['extra_count']);
if ($this->db->trans_status() === FALSE)
{
$this->db->trans_rollback();
return FALSE;
}
else
{
$this->db->trans_commit();
return TRUE;
}
}
invoice_id is primary key in DB .

You're attempting to increment the result array but what you really need is to acquire and increment a field value.
//you only need one field so ask only for that
$query = $this->db->query("SELECT invoice_id FROM invoice ORDER BY invoice_id DESC LIMIT 1");
//you really should check to make sure $query is set
// before trying to get a value from it.
//You can add that yourself
//Asked for only one row, so only retrieve one row -> and its contents
$result = $query->row()->invoice_id;
$result ++;
...

I'm guessing you're getting an "Object conversion to String error" on line $invoice_no = $curYear . '-' .$result;
Since $result contains an object and you're using it as a string. Print the $result variable to check how to use the data assigned to it.

Related

Woocommerce - Implementation of query args in the reviews counting graph only for the currently selected language

I have a code that displays reviews graph of the entire website and divides them into sections according to ratings. The problem is that this code calculates the total reviews of the whole website. I would need to filter the total reviews count according to the currently chosen language. I use WPML. Any advice?
Code:
function display_all_product_review_histogram($minimum_rating, $maximum_rating){
$all_product_review_average_rating = get_all_product_review_average_rating($minimum_rating, $maximum_rating);
$total_ratings = $all_product_review_average_rating[0]["total_ratings"];
$get_all_product_review_counts_by_ratings = get_all_product_review_counts_by_ratings($minimum_rating, $maximum_rating);
if($get_all_product_review_counts_by_ratings){
$output = '';
$sum = 0;
$total = 0;
$raw_percentages_array = array();
$percentages_array = array();
//When working with rounded percentages, we must make sure the total percentages add up to 100%.
//Creating array of rating values and its percentage
foreach ($get_all_product_review_counts_by_ratings as $key => $rating) {
$percentage = round($rating["amount"] / $total_ratings, 2) * 100;
$raw_percentages_array[] = array("value" => $rating["value"], "percent_of_total" => $percentage, 'amount'=> $rating["amount"]);
}
//Counting the total of our percents
foreach($raw_percentages_array as $key => $percent) {
$total += $percent[ "percent_of_total" ];
}
//Creating an array that will have the actual percentages after the rounding has been applied to it.
//This will help to see if we have 100% or we are not aligned
foreach($raw_percentages_array as $key => $percent){
$percentages_array[$percent["value"]] = round(($percent["percent_of_total"]/$total) * 100, 0);
}
$sum = array_sum($percentages_array); //Again counting the total of our new percents to see if it adds up to 100%
if($sum != 100){ //If we do not have 100%, then we will alter the highest percentage value so that we get a total of 100%
$highest_percentage_key = array_keys($percentages_array, max($percentages_array)); //Getting key of the highest percentage value
$percentages_array[$highest_percentage_key[0]] = 100 - ($sum - max($percentages_array)); //Alterning the percentage
}
//Now we are ready to create the output that will give us 100% in total
$r_count = 0;
$output .= "<div class='product-review-histogram'>";
foreach ($percentages_array as $key => $percentage) {
$output .= "<div class='histogram-row star-rating-". $key ."'>";
$output .= "<div class='histogram-col-1'>". $key ." star</div>";
$output .= "<div class='histogram-col-2'><div class='histogram-meter-bar'><div class='histogram-bar-temperature' style='width: ". $percentage ."%'></div></div></div>";
$output .= "<div class='histogram-col-3'>". $raw_percentages_array[$r_count]['amount'] ."</div>";
$output .= "</div>";
$r_count++;
}
$output .= "</div>";
return $output;
}else{
return;
}
}
UPDATE - sharing code of get_all_product_review_average_rating function:
function get_all_product_review_average_rating($minimum_rating, $maximum_rating){
$get_all_product_review_counts_by_ratings = get_all_product_review_counts_by_ratings($minimum_rating, $maximum_rating);
if($get_all_product_review_counts_by_ratings){ //If we have reviews
$average_rating_results = array();
$total_ratings = 0;
$total_rating_value = 0;
foreach ($get_all_product_review_counts_by_ratings as $key => $rating) {
$total_ratings = $total_ratings + $rating["amount"];
$current_rating_value = $rating["amount"] * $rating["value"];
$total_rating_value = $total_rating_value + $current_rating_value;
}
$average_rating = number_format($total_rating_value / $total_ratings, 1); //Rounding value to one decimal place
$average_rating_results[] = array(
"total_ratings" => $total_ratings,
"average_rating" => $average_rating
);
return $average_rating_results;
}else{
return;
}
}
UPDATE2 - sharing more of the functions related to the graph
function get_all_product_review_ratings(){
global $wpdb;
if ( false === ( $review_ratings = get_transient( 'all_product_review_ratings' ))){ //Checking if we have previously cached query results in order to save resources and increase speed
$review_ratings = $wpdb->get_results("
SELECT meta_value
FROM {$wpdb->prefix}commentmeta as commentmeta
JOIN {$wpdb->prefix}comments as comments ON comments.comment_id = commentmeta.comment_id
WHERE commentmeta.meta_key = 'rating' AND comments.comment_approved = 1
ORDER BY commentmeta.meta_value
", ARRAY_A);
$expiration = 60 * 5; //Expiring query results after 5 minutes
set_transient( 'all_product_review_ratings', $review_ratings, $expiration ); //Temporarily storing cached data in the database by giving it a custom name and a timeframe after which it will expire and be deleted
return $review_ratings;
}else{
return $review_ratings;
}
}
WHAT DO WE NEED TO CHANGE TO GET THIS IS PROBABLY THIS PART OF THE CODE:
$review_ratings = $wpdb->get_results("
SELECT meta_value
FROM {$wpdb->prefix}commentmeta as commentmeta
JOIN {$wpdb->prefix}comments as comments ON comments.comment_id = commentmeta.comment_id
WHERE commentmeta.meta_key = 'rating' AND comments.comment_approved = 1
ORDER BY commentmeta.meta_value
", ARRAY_A);
UPDATE 3:
function get_all_product_review_counts_by_ratings($minimum_rating, $maximum_rating){
$all_product_review_ratings = get_all_product_review_ratings();
if($all_product_review_ratings){ //If we have reviews
$all_product_review_ratings_one_dimensional_array = array_map("current", $all_product_review_ratings); //Converting two dimensional array to one dimensional array
$rating_counts = array_count_values($all_product_review_ratings_one_dimensional_array); //Creating array that consists of rating counts
$ratings = array();
while($maximum_rating >= $minimum_rating){
if(array_key_exists($maximum_rating, $rating_counts)){
$star_count = $rating_counts[$maximum_rating];
}else{
$star_count = 0;
}
//Creating array that contains information about
$ratings[] = array(
"value" => $maximum_rating,
"amount" => $star_count
);
$maximum_rating--;
}
return $ratings;
}else{
return;
}
}
function get_all_product_review_ratings() {
global $wpdb;
if (false === ( $review_ratings = get_transient('all_product_review_ratings'))) { //Checking if we have previously cached query results in order to save resources and increase speed
$review_ratings = array();
$args = array(
'status' => 'approve',
'type' => 'review',
'paged' => 0,
'meta_query' => array(
array(
'key' => 'verified',
'value' => 1
)
));
// The Query for getting reviews - WPML respected
$comments_query = new WP_Comment_Query;
$comments = $comments_query->query($args);
foreach ($comments as $comment) {
$review_ratings[] = get_comment_meta($comment->comment_ID, 'rating', 1);
}
$expiration = 60 * 5; //Expiring query results after 5 minutes
set_transient('all_product_review_ratings', $review_ratings, $expiration); //Temporarily storing cached data in the database by giving it a custom name and a timeframe after which it will expire and be deleted
return $review_ratings;
} else {
return $review_ratings;
}
}

php call a class function in loop multiple time issue

I have an issue with one of API, where this API will create Order information. Each Order represents 1 buyer with multiple items. I want to loop the items in my API method. But, when I try to loop the function, it only stores the first array value, which is not what I want. I want to store a whole array of values to the Database.
Here is the API Code:
$s = $data->ItemIDs;
if($order->CreateOrderInfo()){
echo 'Order created successfully.';
echo "---";
for($i = 0; $i < sizeof($s); $i++){
$order->ItemCode = $s[$i];
$order->GetItemInfo();
if ($order->ItemCode != null){
$item_array = array(
'UserMememberNo' => $order->UserMememberNo,
'Image' => $order->Image,
'Description' => $order->Description,
'Price' => $order->Price,
'ItemBrand' => $order->ItemBrand,
'ItemModel' => $order->ItemModel
);
//GET DATA FOR ITEM TABLE
$order->ItemGUID = $data->ItemGUID;
$order->ItemName = $order->Description;
$order->ItemPrice = $order->Price;
$order->ItemQuantity = $data->ItemQuantity;
$order->ItemVariation1 = $data->ItemVariation1;
$order->ItemVariation2 = $data->ItemVariation2;
$order->ItemVariation3 = $data->ItemVariation3;
$order->ItemVariation4 = $data->ItemVariation4;
$order->ItemVariation5 = $data->ItemVariation5;
}
else{
echo json_encode('No item Found');
}
if($order->CreateItemInfo())
{
echo 'Item created';
}else{
echo 'Unable to create item';
echo '----';
}
}
if($order->CreateBuyerInfo()){
echo 'Buyer information created';
}else{
echo 'Unable to create buyer information';
}
Here is the model. This model is for inserting the values into the Database:
//CREATE FUNCTION FOR ITEM TABLE
public function CreateItemInfo() {
$sqlQuery = "INSERT INTO ".$this->item_info_table."
SET
GUID = :GUID,
ItemGUID = :ItemGUID,
ItemName = :ItemName,
ItemPrice = :ItemPrice,
ItemQuantity = :ItemQuantity,
ItemVariation1 = :ItemVariation1,
ItemVariation2 = :ItemVariation2,
ItemVariation3 = :ItemVariation3,
ItemVariation4 = :ItemVariation4";
$stmt = $this->conn->prepare($sqlQuery);
$this->GUID = htmlspecialchars(strip_tags($this->GUID));
$this->ItemGUID = htmlspecialchars(strip_tags($this->ItemGUID));
$this->ItemName = htmlspecialchars(strip_tags($this->ItemName));
$this->ItemPrice = htmlspecialchars(strip_tags($this->ItemPrice));
$this->ItemQuantity = htmlspecialchars(strip_tags($this->ItemQuantity));
$this->ItemVariation1 = htmlspecialchars(strip_tags($this->ItemVariation1));
$this->ItemVariation2 = htmlspecialchars(strip_tags($this->ItemVariation2));
$this->ItemVariation3 = htmlspecialchars(strip_tags($this->ItemVariation3));
$this->ItemVariation4 = htmlspecialchars(strip_tags($this->ItemVariation4));
$stmt->bindParam(":GUID", $this->GUID);
$stmt->bindParam(":ItemGUID", $this->ItemGUID);
$stmt->bindParam(":ItemName", $this->ItemName);
$stmt->bindParam(":ItemPrice", $this->ItemPrice);
$stmt->bindParam(":ItemQuantity", $this->ItemQuantity);
$stmt->bindParam(":ItemVariation1", $this->ItemVariation1);
$stmt->bindParam(":ItemVariation2", $this->ItemVariation2);
$stmt->bindParam(":ItemVariation3", $this->ItemVariation3);
$stmt->bindParam(":ItemVariation4", $this->ItemVariation4);
if($stmt->execute()) {
return true;
}
return false;
}
A screenshot below shows the issue, where only the first value of the array is successfully inserted to the Database.
Result of Database Insert

Problem in duplication after clicking submit button multiple times

My main problem is with that code in which when I click on submit buttons many times, it inserts duplication many times in the database in which I need to avoid that. Please help me to solve this problem. These are the two tables in which I am trying to insert. mat_ans_options_choose and mat_answer.
$val = $this->input->post(null, true);
$val['id'] = $this->input->post('id');
$val['sub_type'] = $this->input->post('sub_type');
$val['timeout'] = $this->input->post('timeout');
$val['level'] = $this->input->post('level');
$val['mat_category'] = $this->input->post('mat_category');
$option = $val['option'] = $this->input->post('option');
$type = $this->input->post('type');
$marks = [];
$uid = $this->session->userdata('id');
if (isset($val['id']) && isset($option)) {
$query = $this->db->query("SELECT * FROM mat_ans_options WHERE deleted=0 AND active=1 AND question=" . $val['id']);
$result = $query->result_array();
if ($query->num_rows() > 0) {
$count1 = 1;
foreach ($result as $res) {
if ($res['marks'] == 1) {
break;
} else {
$count1++;
}
}
}
// MAT answers options choose
$query1 = $this->db->query("SELECT * FROM mat_ans_options_choose WHERE deleted=0 AND active=1 AND uid=$uid AND q=" . $val['id']);
$result1 = $query1->result_array();
if ($query1->num_rows() > 0) {} else {
$data1 = [
'uid' => $uid,
'q' => $val['id'],
'option_chose' => $option,
'createdon' => $this->general_model->server_time(),
];
$this->db->insert('mat_ans_options_choose', $data1);
}
if ($count1 == $option) {
$marks = 1;
} else {
$marks = 0;
}
// if($marks==1 || $marks==0)
// {
// MAT answers
$query2 = $this->db->query("SELECT * FROM mat_answers WHERE deleted=0 AND active=1 AND uid=$uid AND q=" . $val['id'] . " AND type=" . $type . " AND sub_type=" . $val['sub_type'] . " AND level=" . $val['level']);
$result2 = $query2->result_array();
if ($query2->num_rows() > 0) {} else {
$data = [
'uid' => $uid,
'q' => $val['id'],
'type' => $type,
'level' => $val['level'],
'sub_type' => $val['sub_type'],
'mat_category' => $val['mat_category'],
'marks' => $marks,
'timeoutstatus' => $val['timeout'],
'createdon' => $this->general_model->server_time(),
];
$this->db->insert('mat_answers', $data);
}
// }
return 1;
} else {
return 0;
}
Use JS in which you disable the button after first click - it will work no matter if you are using AJAX or not.
You can use JS/jQuery to limit the number of requests made on the client side. For example by disabling the button on submit:
$("#my-button").prop("disabled", true);
But if the data is sensitive for duplicates (orders, user registration etc) you should make the request limit server side with PHP. You can achieve this by adding a unique index to the tables, either on user id or on a unique token that is submitted with the html form.
Create UNIQUE index in database for uid and q. The database will not insert same question's id from same user's id mulitple times.

Insert Batch php mysql with check duplicate and sum values of field duplicate

i have 1 million data using foreach.
ex table:
table
the data
data
i want to inserting that's data using batch/multipleinsert, but i have problem when i got duplicate data. if data duplicate i want the field amount will sum and update amount field with sum amount duplicated data.
this is my code before
<?php
foreach ($data_transaksi as $key)
{
if($key['STATUS_COA'] != $key['CHART_OF_ACCOUNT_STATUS'])
{
if($key['ACCOUNT_CATEGORY_CODE'] == '9')
{
$amount = round($key['AMOUNT'],2);
}
else
{
$amount = round($key['AMOUNT'],2) *-1;
}
}
else
{
if($key['ACCOUNT_CATEGORY_CODE'] == '9')
{
$amount = round($key['AMOUNT'],2)*-1;
}
else
{
$amount = round($key['AMOUNT'],2);
}
}
$dt_exsis = $this->ledger_model->cek_data_coa_exsis($key['COA_CODE'],$modul,$ID_USER);
if(empty($dt_exsis['id']))
{
//TRYINSERTINGBATCH
// $datainsert[] = '('.$key['COA_CODE'].','.$amount.','.$ID_USER.',"'.$modul.'")';
// $test = $key['COA_CODE'];
$datainput = array(
'COA_CODE' => $key['COA_CODE'],
'AMOUNT' => $amount,
'MODUL' => $modul,
'USER_ID' => $ID_USER
);
$this->ledger_model->save_rows_to_table($datainput,'finance_lapkue_temp');
}
else
{
$amount_fix = $amount + $dt_exsis['AMOUNT'];
$data=array(
'AMOUNT' => $amount_fix
);
$this->ledger_model->edit_rows_to_table_where($data,'finance_lapkue_temp','id',$dt_exsis['id']);
// $q = "UPDATE finance_lapkue_temp set AMOUNT = '$amount_fix' where id = '".$dt_exsis['id']."'";
// $this->db->query($q);
}
// $data_amount[$key['COA_CODE']] += $amount;
}
?>
if i using this code, the proccess so slow
Good option will to pass only data to DB that you want to insert. All the data cleaning task can be done in controller.
// Create a data array and add all info
$data = [];
//if user does not exist add it in array
if (empty($dt_exist($id))) {
$data[$ID_USER] = array(
'COA_CODE' => $key['COA_CODE'],
'AMOUNT' => $amount,
'MODUL' => $modul,
'USER_ID' => $ID_USER
);
}
else {
//if user exist in $data just modify the amount
if (!empty($data[$ID_USER])) {
$data[$ID_USER]['AMOUNT'] += $dt_exsis['AMOUNT'];
}
else {
// if user does not exist in data create add all info
$data[$dt_exsis['ID_USER']] = array(
'COA_CODE' => $dt_exsis['COA_CODE'],
'AMOUNT' => $dt_exsis['amount'],
'MODUL' => $dt_exsis['modul'],
'USER_ID' => $dt_exsis['ID_USER']
);
}
}
This will save multiple calls to DB and at the end you can pass $data and do multiple insert.

Unique code generation using Last Insert Id in Code Igniter?

I need to create a drcode using the last insert id in the prescribed format,
previously I have used cor php to get the code but now in codeigniter am not able to get the code as the previous one. How can i do this? I am providing my controller and model
Controller
public function newdoctor_post() {
$employee_id = $this->post('EMPLOYEE_ID');
$doctorname = $this->post('DOCTOR_NAME');
$mobilenumber = $this->post('DRMOBILE');
$users_data = $this->Rest_user_model->doctor_exists($mobilenumber);
if ($users_data == 1) {
$message = ['status' => 2,
// 'result' => array(),
'message' => 'Doctor already registered'];
} else {
$speciality = $this->post('SPECIALITY');
$longitude = $this->post('LONGITUDE');
$latitude = $this->post('LATITUDE');
$drcode = $this->post('DRCODE');
$createdon = date('Y-m-d H:i:s');
$insert_array = array('EMPLOYEE_ID' => $employee_id, 'DOCTOR_NAME' => $doctorname, 'DRMOBILE' => $mobilenumber, 'SPECIALITY' => $speciality, 'LONGITUDE' => $longitude, 'LATITUDE' => $latitude, 'CREATEDON' => $createdon);
$users_data = $this->Rest_user_model->doctorregistration($insert_array);
$message = ['status' => 1, // 'result' => $users_data,
'message' => 'Doctor Registered Successfully'];
}
$this->set_response($message, REST_Controller::HTTP_OK);
}
Model
public function doctorregistration($data) {
if (!empty($data)) {
$this->db->insert('DOCTORDETAILS', $data);
return $this->db->insert_id();
}
return 0;
}
Code Generation
$sql1="SELECT DRCODE FROM DOCTORDETAILS ORDER BY DRCODEDESC LIMIT 1";
$query=mysql_query($sql1);
if (!$sql1) { // add this check.
die('Invalid query: ' . mysql_error());
}
$output_array2=array();
while($row=mysql_fetch_assoc($query))
{
$ids=$row['DRCODE'];
}
// echo $ids;
if($ids){
$su=1;
$num =$num = 'DR' . str_pad($su + substr($ids, 3), 6, '0', STR_PAD_LEFT);;
$unique=$num;
}else{
$unique='DR000001';
}
Try this - replace this code below with your Code Generation code.
$sql1="SELECT DRCODE FROM DOCTORDETAILS ORDER BY DRCODEDESC LIMIT 1";
$query=$this->db->query($sql1);
if (!$sql1) { // add this check.
die('Invalid query');
}
$output_array2=array();
foreach($query->result_array() as $row)
{
$ids=$row['DRCODE'];
}
// echo $ids;
if($ids){
$su=1;
$num =$num = 'DR' . str_pad($su + substr($ids, 3), 6, '0', STR_PAD_LEFT);;
$unique=$num;
}else{
$unique='DR000001';
}
You should make a different column fr drcode, leave it blank.
Now make a trigger on insert, it should be run after insert.
I am assuming DOCTORDETAILS as table name and drcode as column name
DELIMITER $$
CREATE TRIGGER trigger_after_insert
AFTER INSERT ON `DOCTORDETAILS` FOR EACH ROW
begin
UPDATE `DOCTORDETAILS` set drcode=CONCAT('DR',new.id);
END$$
DELIMITER ;
The trigger create a new string with your new auto generated id
Trigger in MySQL:
TechonTheNet
MySQL Trigger on after insert

Categories