diff --git a/application/controllers/Attributes.php b/application/controllers/Attributes.php index 440da8ca9..a48218233 100644 --- a/application/controllers/Attributes.php +++ b/application/controllers/Attributes.php @@ -16,9 +16,9 @@ class Attributes extends Secure_Controller $this->load->view('attributes/manage', $data); } - /* - Returns customer table data rows. This will be called with AJAX. - */ + /** + * Returns customer table data rows. This will be called with AJAX. + */ public function search() { $search = $this->input->get('search'); @@ -44,7 +44,7 @@ class Attributes extends Secure_Controller public function save_attribute_value($attribute_value) { - $success = $this->Attribute->save_value(urldecode($attribute_value), $this->input->post('definition_id'), $this->input->post('item_id'), $this->input->post('attribute_id')); + $success = $this->Attribute->save_value(urldecode($attribute_value), $this->input->post('definition_id'), $this->input->post('item_id'), $this->input->post('attribute_id')); echo json_encode(array('success' => $success != 0)); } @@ -58,7 +58,6 @@ class Attributes extends Secure_Controller public function save_definition($definition_id = -1) { - $definition_flags = 0; $flags = (empty($this->input->post('definition_flags'))) ? array() : $this->input->post('definition_flags'); @@ -68,7 +67,7 @@ class Attributes extends Secure_Controller $definition_flags |= $flag; } - //Save definition data + //Save definition data $definition_data = array( 'definition_name' => $this->input->post('definition_name'), 'definition_unit' => $this->input->post('definition_unit') != '' ? $this->input->post('definition_unit') : NULL, @@ -85,7 +84,7 @@ class Attributes extends Secure_Controller if($this->Attribute->save_definition($definition_data, $definition_id)) { - //New definition + //New definition if($definition_id == -1) { $definition_values = json_decode($this->input->post('definition_values')); @@ -96,15 +95,17 @@ class Attributes extends Secure_Controller } echo json_encode(array('success' => TRUE, 'message' => $this->lang->line('attributes_definition_successful_adding').' '. - $definition_name, 'id' => $definition_data['definition_id'])); + $definition_name, 'id' => $definition_data['definition_id'])); } - else //Existing definition + //Existing definition + else { echo json_encode(array('success' => TRUE, 'message' => $this->lang->line('attributes_definition_successful_updating').' '. - $definition_name, 'id' => $definition_id)); + $definition_name, 'id' => $definition_id)); } } - else//failure + //Failure + else { echo json_encode(array('success' => FALSE, 'message' => $this->lang->line('attributes_definition_error_adding_updating', $definition_name), 'id' => -1)); } @@ -180,5 +181,4 @@ class Attributes extends Secure_Controller echo json_encode(array('success' => FALSE, 'message' => $this->lang->line('attributes_definition_cannot_be_deleted'))); } } - -} +} \ No newline at end of file diff --git a/application/controllers/Items.php b/application/controllers/Items.php index d5ca2d2cc..4ae98f918 100644 --- a/application/controllers/Items.php +++ b/application/controllers/Items.php @@ -16,11 +16,10 @@ class Items extends Secure_Controller $this->session->set_userdata('allow_temp_items', 0); $data['table_headers'] = $this->xss_clean(get_items_manage_table_headers()); - $data['stock_location'] = $this->xss_clean($this->item_lib->get_item_location()); $data['stock_locations'] = $this->xss_clean($this->Stock_location->get_allowed_locations()); - // filters that will be loaded in the multiselect dropdown + //Filters that will be loaded in the multiselect dropdown $data['filters'] = array('empty_upc' => $this->lang->line('items_empty_upc_items'), 'low_inventory' => $this->lang->line('items_low_inventory_items'), 'is_serialized' => $this->lang->line('items_serialized_items'), @@ -59,7 +58,7 @@ class Items extends Secure_Controller 'temporary' => FALSE, 'definition_ids' => array_keys($definition_names)); - // check if any filter is set in the multiselect dropdown + //Check if any filter is set in the multiselect dropdown $filledup = array_fill_keys($this->input->get('filters'), TRUE); $filters = array_merge($filters, $filledup); @@ -85,16 +84,17 @@ class Items extends Secure_Controller $this->load->helper('file'); $this->load->library('image_lib'); - // in this context, $pic_filename always has .ext + //In this context, $pic_filename always has .ext $ext = pathinfo($pic_filename, PATHINFO_EXTENSION); $images = glob('./uploads/item_pics/' . $pic_filename); - // make sure we pick only the file name, without extension + //Make sure we pick only the file name, without extension $base_path = './uploads/item_pics/' . pathinfo($pic_filename, PATHINFO_FILENAME); if(sizeof($images) > 0) { $image_path = $images[0]; $thumb_path = $base_path . $this->image_lib->thumb_marker . '.' . $ext; + if(sizeof($images) < 2) { $config['image_library'] = 'gd2'; @@ -131,7 +131,6 @@ class Items extends Secure_Controller echo json_encode($suggestions); } - public function suggest_low_sell() { $suggestions = $this->xss_clean($this->Item->get_low_sell_suggestions($this->input->post_get('name'))); @@ -139,7 +138,6 @@ class Items extends Secure_Controller echo json_encode($suggestions); } - public function suggest_kits() { $suggestions = $this->xss_clean($this->Item->get_kit_search_suggestions($this->input->post_get('term'), @@ -188,7 +186,7 @@ class Items extends Secure_Controller $data = array(); } - // allow_temp_items is set in the index function of items.php or sales.php + //allow_temp_items is set in the index function of items.php or sales.php $data['allow_temp_item'] = $this->session->userdata('allow_temp_items'); $data['item_tax_info'] = $this->xss_clean($this->Item_taxes->get_info($item_id)); $data['default_tax_1_rate'] = ''; @@ -237,13 +235,14 @@ class Items extends Secure_Controller $item_info->receiving_quantity = 1; $item_info->reorder_level = 1; - $item_info->item_type = ITEM; // standard + $item_info->item_type = ITEM; //Standard $item_info->item_id = $item_id; $item_info->stock_type = HAS_STOCK; $item_info->tax_category_id = NULL; $item_info->qty_per_pack = 1; $item_info->pack_name = $this->lang->line('items_default_pack_name'); $data['hsn_code'] = ''; + if($use_destination_based_tax) { $item_info->tax_category_id = $this->config->item('default_tax_category'); @@ -251,16 +250,18 @@ class Items extends Secure_Controller } $data['standard_item_locked'] = ($data['item_kit_disabled'] && $item_info->item_type == ITEM_KIT - && !$data['allow_temp_item'] - && !($this->config->item('derive_sale_quantity') == '1')); + && !$data['allow_temp_item'] + & !($this->config->item('derive_sale_quantity') == '1')); $data['item_info'] = $item_info; $suppliers = array('' => $this->lang->line('items_none')); + foreach($this->Supplier->get_all()->result_array() as $row) { $suppliers[$this->xss_clean($row['person_id'])] = $this->xss_clean($row['company_name']); } + $data['suppliers'] = $suppliers; $data['selected_supplier'] = $item_info->supplier_id; @@ -300,18 +301,21 @@ class Items extends Secure_Controller $data['logo_exists'] = $item_info->pic_filename != ''; $ext = pathinfo($item_info->pic_filename, PATHINFO_EXTENSION); + if($ext == '') { - // if file extension is not found guess it (legacy) + //If file extension is not found guess it (legacy) $images = glob('./uploads/item_pics/' . $item_info->pic_filename . '.*'); } else { - // else just pick that file + //Else just pick that file $images = glob('./uploads/item_pics/' . $item_info->pic_filename); } - $data['image_path'] = sizeof($images) > 0 ? base_url($images[0]) : ''; - $stock_locations = $this->Stock_location->get_undeleted_all()->result_array(); + + $data['image_path'] = sizeof($images) > 0 ? base_url($images[0]) : ''; + $stock_locations = $this->Stock_location->get_undeleted_all()->result_array(); + foreach($stock_locations as $location) { $location = $this->xss_clean($location); @@ -393,28 +397,26 @@ class Items extends Secure_Controller $data['barcode_config'] = $config; - // check the list of items to see if any item_number field is empty + //Check the list of items to see if any item_number field is empty foreach($result as &$item) { $item = $this->xss_clean($item); - // update the barcode field if empty / NULL with the newly generated barcode + //Update the barcode field if empty / NULL with the newly generated barcode if(empty($item['item_number']) && $this->config->item('barcode_generate_if_empty')) { - // get the newly generated barcode + // get the newly generated barcode $barcode_instance = Barcode_lib::barcode_instance($item, $config); $item['item_number'] = $barcode_instance->getData(); $save_item = array('item_number' => $item['item_number']); - // update the item in the database in order to save the barcode field - $this->Item->save($save_item, $item['item_id']); + $this->Item->save($save_item, $item['item_id']); // update the item in the database in order to save the barcode field } } $data['items'] = $result; - // display barcodes - $this->load->view('barcodes/barcode_sheet', $data); + $this->load->view('barcodes/barcode_sheet', $data); // display barcodes } public function attributes($item_id) @@ -488,7 +490,7 @@ class Items extends Secure_Controller } $default_pack_name = $this->lang->line('items_default_pack_name'); - //Save item data + //Save item data $item_data = array( 'name' => $this->input->post('name'), 'description' => $this->input->post('description'), @@ -518,6 +520,7 @@ class Items extends Secure_Controller } $x = $this->input->post('tax_category_id'); + if(!isset($x)) { $item_data['tax_category_id'] = ''; @@ -529,7 +532,7 @@ class Items extends Secure_Controller if(!empty($upload_data['orig_name'])) { - // XSS file image sanity check + // XSS file image sanity check if($this->xss_clean($upload_data['raw_name'], TRUE) === TRUE) { $item_data['pic_filename'] = $upload_data['raw_name']; @@ -542,7 +545,8 @@ class Items extends Secure_Controller { $success = TRUE; $new_item = FALSE; - //New item + + //New item if($item_id == -1) { $item_id = $item_data['item_id']; @@ -568,7 +572,7 @@ class Items extends Secure_Controller $success &= $this->Item_taxes->save($items_taxes_data, $item_id); } - //Save item quantity + //Save item quantity $stock_locations = $this->Stock_location->get_undeleted_all()->result_array(); foreach($stock_locations as $location) { @@ -581,8 +585,8 @@ class Items extends Secure_Controller 'location_id' => $location['location_id'], 'quantity' => $updated_quantity); - $item_quantity = $this->Item_quantity->get_item_quantity($item_id, $location['location_id']); + if($item_quantity->quantity != $updated_quantity || $new_item) { $success &= $this->Item_quantity->save($location_detail, $item_id, $location['location_id']); @@ -600,10 +604,11 @@ class Items extends Secure_Controller } } - // Save item attributes + // Save item attributes $attribute_links = $this->input->post('attribute_links') != NULL ? $this->input->post('attribute_links') : array(); $attribute_ids = $this->input->post('attribute_ids'); $this->Attribute->delete_link($item_id); + foreach($attribute_links as $definition_id => $attribute_id) { $definition_type = $this->Attribute->get_info($definition_id)->definition_type; @@ -627,7 +632,7 @@ class Items extends Secure_Controller echo json_encode(array('success' => FALSE, 'message' => $message, 'id' => $item_id)); } } - else // failure + else //Failure { $message = $this->xss_clean($this->lang->line('items_error_adding_updating') . ' ' . $item_data['name']); @@ -657,17 +662,19 @@ class Items extends Secure_Controller echo !$exists ? 'true' : 'false'; } + /* + * Let files be uploaded with their original name + */ private function _handle_image_upload() { - /* Let files be uploaded with their original name */ - - // load upload library + //Load upload library $config = array('upload_path' => './uploads/item_pics/', 'allowed_types' => 'gif|jpg|png', 'max_size' => '100', 'max_width' => '640', 'max_height' => '480' ); + $this->load->library('upload', $config); $this->upload->do_upload('item_image'); @@ -698,7 +705,7 @@ class Items extends Secure_Controller $this->Inventory->insert($inv_data); - //Update stock quantity + //Update stock quantity $item_quantity = $this->Item_quantity->get_item_quantity($item_id, $location_id); $item_quantity_data = array( 'item_id' => $item_id, @@ -712,7 +719,7 @@ class Items extends Secure_Controller echo json_encode(array('success' => TRUE, 'message' => $message, 'id' => $item_id)); } - else//failure + else //failure { $message = $this->xss_clean($this->lang->line('items_error_adding_updating') . ' ' . $cur_item_info->name); @@ -727,7 +734,7 @@ class Items extends Secure_Controller foreach($_POST as $key => $value) { - //This field is nullable, so treat it differently + //This field is nullable, so treat it differently if($key == 'supplier_id' && $value != '') { $item_data["$key"] = $value; @@ -822,51 +829,47 @@ class Items extends Secure_Controller for($i = 1; $i < count($line_array); $i++) { $invalidated = FALSE; - $line = array_combine($keys,$this->xss_clean($line_array[$i])); //Build a XSS-cleaned associative array with the row to use to assign values - if(!empty($line)) + $line = array_combine($keys,$this->xss_clean($line_array[$i])); //Build a XSS-cleaned associative array with the row to use to assign values + + $item_data = array( + 'name' => $line['Item Name'], + 'description' => $line['Description'], + 'category' => $line['Category'], + 'cost_price' => $line['Cost Price'], + 'unit_price' => $line['Unit Price'], + 'reorder_level' => $line['Reorder Level'], + 'supplier_id' => $this->Supplier->exists($line['Supplier ID']) ? $line['Supplier ID'] : NULL, + 'allow_alt_description' => empty($line['Allow Alt Description'])? '0' : '1', + 'is_serialized' => empty($line['Item has Serial Number'])? '0' : '1', + 'hsn_code' => $line['HSN'], + 'pic_filename' => $line['item_image'] + ); + + $item_number = $line['Barcode']; + + if(!empty($item_number)) { - $item_data = array( - 'name' => $line['Item Name'], - 'description' => $line['Description'], - 'category' => $line['Category'], - 'cost_price' => $line['Cost Price'], - 'unit_price' => $line['Unit Price'], - 'reorder_level' => $line['Reorder Level'], - 'supplier_id' => $this->Supplier->exists($line['Supplier ID']) ? $line['Supplier ID'] : NULL, - 'allow_alt_description' => $line['Allow Alt Description'] != '' ? '1' : '0', - 'is_serialized' => $line['Item has Serial Number'] != '' ? '1' : '0', - 'hsn_code' => $line['HSN'], - 'pic_filename' => $line['item_image'] - ); - - $item_number = $line['Barcode']; - - if($item_number != '') - { - $item_data['item_number'] = $item_number; - $invalidated = $this->Item->item_number_exists($item_number); - } - - //Sanity check of data - if(!$invalidated) - { - $invalidated = $this->data_error_check($line, $item_data); - } - } - else - { - $invalidated = TRUE; + $item_data['item_number'] = $item_number; + $invalidated = $this->Item->item_number_exists($item_number); } - //Save to database + //Sanity check of data + if(!$invalidated) + { + $invalidated = $this->data_error_check($line, $item_data); + } + + //Save to database if(!$invalidated && $this->Item->save($item_data)) { $this->save_tax_data($line, $item_data); $this->save_inventory_quantities($line, $item_data); $this->save_attribute_data($line, $item_data); } - else //insert or update item failure + + //Insert or update item failure + else { $failed_row = $i+1; $failCodes[] = $failed_row; @@ -894,7 +897,7 @@ class Items extends Secure_Controller } /** - * Checks the entire line of data for errors + * Checks the entire line of data in an import file for errors * * @param array $line * @param array $item_data @@ -903,21 +906,25 @@ class Items extends Secure_Controller */ private function data_error_check($line, $item_data) { - //Check for empty required fields + //Check for empty required fields $check_for_empty = array( $item_data['name'], $item_data['category'], - $item_data['cost_price'], $item_data['unit_price'] ); - if(in_array('',$check_for_empty,true)) + foreach($check_for_empty as $key => $val) { - log_message("ERROR","Empty required value"); - return TRUE; //Return fail on empty required fields + if (empty($val)) + { + log_message("ERROR","Empty required value"); + return TRUE; //Return fail on empty required fields + } } - //Build array of fields to check for numerics + $item_data['cost_price'] = empty($item_data['cost_price']) ? 0 : 1; //Allow for zero wholesale price + + //Build array of fields to check for numerics $check_for_numeric_values = array( $item_data['cost_price'], $item_data['unit_price'], @@ -927,7 +934,7 @@ class Items extends Secure_Controller $line['Tax 2 Percent'] ); - //Add in Stock Location values to check for numeric + //Add in Stock Location values to check for numeric $allowed_locations = $this->Stock_location->get_allowed_locations(); foreach($allowed_locations as $location_id => $location_name) @@ -935,7 +942,7 @@ class Items extends Secure_Controller $check_for_numeric_values[] = $line['location_'. $location_name]; } - //Check for non-numeric values which require numeric + //Check for non-numeric values which require numeric foreach($check_for_numeric_values as $value) { if(!is_numeric($value) && $value != '') @@ -945,8 +952,9 @@ class Items extends Secure_Controller } } - //Check Attribute Data + //Check Attribute Data $definition_names = $this->Attribute->get_definition_names(); + unset($definition_names[-1]); foreach($definition_names as $definition_name) { @@ -961,7 +969,7 @@ class Items extends Secure_Controller $dropdown_values = $this->Attribute->get_definition_values($attribute_data['definition_id']); $dropdown_values[] = ''; - if(in_array($attribute_value, $dropdown_values) === FALSE) + if(in_array($attribute_value, $dropdown_values) === FALSE && !empty($attribute_value)) { log_message("ERROR","Value: '$attribute_value' is not an acceptable DROPDOWN value"); return TRUE; @@ -969,17 +977,17 @@ class Items extends Secure_Controller } else if($attribute_type == 'DECIMAL') { - if(!is_numeric($attribute_value) && $attribute_value != '') + if(!is_numeric($attribute_value) && !empty($attribute_value)) { - log_message("ERROR","Decimal required: '$attribute_value' is not an acceptable DECIMAL value"); + log_message("ERROR","'$attribute_value' is not an acceptable DECIMAL value"); return TRUE; } } else if($attribute_type == 'DATETIME') { - if(strtotime($attribute_value) === FALSE) + if(strtotime($attribute_value) === FALSE && !empty($attribute_value)) { - log_message("ERROR","Datetime required: '$attribute_value' is not an acceptable DATETIME value"); + log_message("ERROR","'$attribute_value' is not an acceptable DATETIME value."); return TRUE; } } @@ -990,6 +998,8 @@ class Items extends Secure_Controller } /** + * Saves attribute data found in the CSV import. + * * @param line * @param failCodes * @param attribute_data @@ -997,14 +1007,36 @@ class Items extends Secure_Controller private function save_attribute_data($line, $item_data) { $definition_names = $this->Attribute->get_definition_names(); + unset($definition_names[-1]); foreach($definition_names as $definition_name) { - if(!empty($line['attribute_' . $definition_name])) + //Create attribute value + if(!empty($line['attribute_' . $definition_name]) || $line['attribute_' . $definition_name] == '0') { - //Create attribute value $attribute_data = $this->Attribute->get_definition_by_name($definition_name)[0]; - $status = $this->Attribute->save_value($line['attribute_' . $definition_name], $attribute_data['definition_id'], $item_data['item_id'], FALSE, $attribute_data['definition_type']); + + //CHECKBOX Attribute types (zero value creates attribute and marks it as unchecked) + if($attribute_data['definition_type'] == 'CHECKBOX') + { + //FALSE and '0' value creates checkbox and marks it as unchecked. + if(strcasecmp($line['attribute_' . $definition_name],'FALSE') == 0 || $line['attribute_' . $definition_name] == '0') + { + $line['attribute_' . $definition_name] = '0'; + } + else + { + $line['attribute_' . $definition_name] = '1'; + } + + $status = $this->Attribute->save_value($line['attribute_' . $definition_name], $attribute_data['definition_id'], $item_data['item_id'], FALSE, $attribute_data['definition_type']); + } + + //All other Attribute types (0 value means attribute not created) + elseif(!empty($line['attribute_' . $definition_name])) + { + $status = $this->Attribute->save_value($line['attribute_' . $definition_name], $attribute_data['definition_id'], $item_data['item_id'], FALSE, $attribute_data['definition_type']); + } if($status === FALSE) { @@ -1022,7 +1054,7 @@ class Items extends Secure_Controller */ private function save_inventory_quantities($line, $item_data) { - //Quantities & Inventory Section + //Quantities & Inventory Section $employee_id = $this->Employee->get_logged_in_employee_info()->person_id; $emp_info = $this->Employee->get_info($employee_id); $comment = $this->lang->line('items_inventory_CSV_import_quantity'); @@ -1086,7 +1118,6 @@ class Items extends Secure_Controller } } - /** * Guess whether file extension is not in the table field, if it isn't, then it's an old-format (formerly pic_id) field, so we guess the right filename and update the table * @@ -1096,7 +1127,7 @@ class Items extends Secure_Controller { $filename = pathinfo($item->pic_filename, PATHINFO_FILENAME); - // if the field is empty there's nothing to check + // if the field is empty there's nothing to check if(!empty($filename)) { $ext = pathinfo($item->pic_filename, PATHINFO_EXTENSION); @@ -1113,4 +1144,4 @@ class Items extends Secure_Controller } } } -?> +?> \ No newline at end of file diff --git a/application/helpers/importfile_helper.php b/application/helpers/importfile_helper.php index ff2dd878e..97da2baba 100644 --- a/application/helpers/importfile_helper.php +++ b/application/helpers/importfile_helper.php @@ -11,7 +11,7 @@ function generate_import_items_csv($stock_locations,$attributes) $csv_headers .= 'Barcode,"Item Name",Category,"Supplier ID","Cost Price","Unit Price","Tax 1 Name","Tax 1 Percent","Tax 2 Name","Tax 2 Percent","Reorder Level",Description,"Allow Alt Description","Item has Serial Number",item_image,HSN'; $csv_headers .= generate_stock_location_headers($stock_locations); $csv_headers .= generate_attribute_headers($attributes); - + return $csv_headers; } @@ -23,12 +23,12 @@ function generate_import_items_csv($stock_locations,$attributes) function generate_stock_location_headers($locations) { $location_headers = ""; - + foreach($locations as $location_id => $location_name) { $location_headers .= ',"location_' . $location_name . '"'; } - + return $location_headers; } @@ -41,12 +41,12 @@ function generate_attribute_headers($attribute_names) { $attribute_headers = ""; unset($attribute_names[-1]); - + foreach($attribute_names as $attribute_name) { $attribute_headers .= ',"attribute_' . $attribute_name . '"'; } - + return $attribute_headers; } @@ -59,7 +59,7 @@ function generate_attribute_headers($attribute_names) function get_csv_file($file_name) { ini_set("auto_detect_line_endings", true); - + if(($csv_file = fopen($file_name,'r')) !== FALSE) { //Skip Byte-Order Mark @@ -67,17 +67,21 @@ function get_csv_file($file_name) { fseek($csv_file, 3); } - + while (($data = fgetcsv($csv_file)) !== FALSE) { - $line_array[] = $data; + //Skip empty lines + if(array(null) !== $data) + { + $line_array[] = $data; + } } } else { return FALSE; } - + return $line_array; } @@ -91,9 +95,9 @@ function bom_exists(&$file_handle) { $str = fread($file_handle,3); rewind($file_handle); - + $bom = pack("CCC", 0xef, 0xbb, 0xbf); - + if (0 === strncmp($str, $bom, 3)) { return TRUE; diff --git a/application/models/Attribute.php b/application/models/Attribute.php index d0905f6e8..64f15f189 100644 --- a/application/models/Attribute.php +++ b/application/models/Attribute.php @@ -5,8 +5,9 @@ define('DROPDOWN', 'DROPDOWN'); define('DECIMAL', 'DECIMAL'); define('DATE', 'DATE'); define('TEXT', 'TEXT'); +define('CHECKBOX', 'CHECKBOX'); -const DEFINITION_TYPES = [GROUP, DROPDOWN, DECIMAL, TEXT, DATE]; +const DEFINITION_TYPES = [GROUP, DROPDOWN, DECIMAL, TEXT, DATE, CHECKBOX]; /** * Attribute class @@ -50,8 +51,8 @@ class Attribute extends CI_Model else { $this->db->where('definition_id', $definition_id); - } + $this->db->where('item_id', $item_id); return ($this->db->get()->num_rows() > 0); @@ -92,10 +93,10 @@ class Attribute extends CI_Model } else { - //Get empty base parent object, as $item_id is NOT an item + //Get empty base parent object, as $item_id is NOT an item $item_obj = new stdClass(); - //Get all the fields from items table + //Get all the fields from items table foreach($this->db->list_fields('attribute_definitions') as $field) { $item_obj->$field = ''; @@ -194,7 +195,6 @@ class Attribute extends CI_Model return $this->_to_array($results, 'definition_id', 'definition_name'); } - /** * Returns an array of attribute definition names and IDs * @@ -305,10 +305,11 @@ class Attribute extends CI_Model { $success = FALSE; - //From TEXT to DATETIME + //From TEXT if($from_type === TEXT) { - if($to_type === DATE || $to_type === DECIMAL) + //To DATETIME or DECIMAL + if(in_array($to_type, [DATE, DECIMAL], TRUE)) { $field = ($to_type === DATE ? 'attribute_date' : 'attribute_decimal'); @@ -327,27 +328,64 @@ class Attribute extends CI_Model $this->db->trans_complete(); } } + + //To DROPDOWN or CHECKBOX else if($to_type === DROPDOWN) { $success = TRUE; } + else if($to_type === CHECKBOX) + { + $checkbox_attribute_values = $this->checkbox_attribute_values($definition_id); + + $this->db->trans_start(); + + $query = 'UPDATE ospos_attribute_values values '; + $query .= 'INNER JOIN ospos_attribute_links links '; + $query .= 'ON values.attribute_id = links.attribute_id '; + $query .= "SET links.attribute_id = IF((values.attribute_value IN('FALSE','0','') OR (values.attribute_value IS NULL)), $checkbox_attribute_values[0], $checkbox_attribute_values[1]) "; + $query .= 'WHERE definition_id = ' . $this->db->escape($definition_id); + $success = $this->db->query($query); + + $this->db->trans_complete(); + } } - //From DROPDOWN to TEXT + //From DROPDOWN else if($from_type === DROPDOWN) { - //From DROPDOWN to TEXT - $this->db->trans_start(); + //To TEXT + if(in_array($to_type, [TEXT, CHECKBOX], TRUE)) + { + $this->db->trans_start(); - $this->db->from('ospos_attribute_links'); - $this->db->where('definition_id',$definition_id); - $this->db->where('item_id', NULL); - $success = $this->db->delete(); + $this->db->from('ospos_attribute_links'); + $this->db->where('definition_id',$definition_id); + $this->db->where('item_id', NULL); + $success = $this->db->delete(); - $this->db->trans_complete(); + $this->db->trans_complete(); + + //To CHECKBOX + if($to_type === CHECKBOX) + { + $checkbox_attribute_values = $this->checkbox_attribute_values($definition_id); + + $this->db->trans_start(); + + $query = 'UPDATE ospos_attribute_values values '; + $query .= 'INNER JOIN ospos_attribute_links links '; + $query .= 'ON values.attribute_id = links.attribute_id '; + $query .= "SET links.attribute_id = IF((values.attribute_value IN('FALSE','0','') OR (values.attribute_value IS NULL)), $checkbox_attribute_values[0], $checkbox_attribute_values[1]) "; + $query .= 'WHERE definition_id = ' . $this->db->escape($definition_id); + $success = $this->db->query($query); + + $this->db->trans_complete(); + } + } } - //Any other allowed conversion does not get checked here + //From any other type else { $success = TRUE; @@ -356,22 +394,40 @@ class Attribute extends CI_Model return $success; } + private function checkbox_attribute_values($definition_id) + { + $zero_attribute_id = $this->value_exists('0'); + $one_attribute_id = $this->value_exists('1'); + + if($zero_attribute_id === FALSE) + { + $zero_attribute_id = $this->save_value('0', $definition_id, FALSE, FALSE, CHECKBOX); + } + + if($one_attribute_id === FALSE) + { + $one_attribute_id = $this->save_value('1', $definition_id, FALSE, FALSE, CHECKBOX); + } + + return array($zero_attribute_id, $one_attribute_id); + } + /* Inserts or updates a definition */ public function save_definition(&$definition_data, $definition_id = -1) { - //Run these queries as a transaction, we want to make sure we do all or nothing + //Run these queries as a transaction, we want to make sure we do all or nothing $this->db->trans_start(); - //Definition doesn't exist + //Definition doesn't exist if($definition_id === -1 || !$this->exists($definition_id)) { $success = $this->db->insert('attribute_definitions', $definition_data); $definition_data['definition_id'] = $this->db->insert_id(); } - //Definition already exists + //Definition already exists else { $this->db->select('definition_type, definition_name'); @@ -475,6 +531,7 @@ class Attribute extends CI_Model $this->db->where('sale_id'); $this->db->where('receiving_id'); } + $this->db->where('item_id', (int) $item_id); $this->db->where('definition_flags & ', $definition_flags); @@ -515,6 +572,7 @@ class Attribute extends CI_Model $this->db->where('deleted', 0); $this->db->where('definition.definition_id', $definition_id); $this->db->order_by('attribute_value'); + foreach($this->db->get()->result() as $row) { $row_array = (array) $row; @@ -528,9 +586,10 @@ class Attribute extends CI_Model { $this->db->trans_start(); + //New Attribute if(empty($attribute_id) || empty($item_id)) { - if(in_array($definition_type, [TEXT, DROPDOWN], TRUE)) + if(in_array($definition_type, [TEXT, DROPDOWN, CHECKBOX], TRUE)) { $attribute_id = $this->value_exists($attribute_value); @@ -549,12 +608,14 @@ class Attribute extends CI_Model } $attribute_id = $attribute_id ? $attribute_id : $this->db->insert_id(); - + $this->db->insert('attribute_links', array( 'attribute_id' => empty($attribute_id) ? NULL : $attribute_id, 'item_id' => empty($item_id) ? NULL : $item_id, 'definition_id' => $definition_id)); } + + //Existing Attribute else { $this->db->where('attribute_id', $attribute_id); @@ -603,4 +664,4 @@ class Attribute extends CI_Model return $this->db->update('attribute_definitions', array('deleted' => 1)); } -} +} \ No newline at end of file diff --git a/application/views/attributes/form.php b/application/views/attributes/form.php index 1b582397f..8b3d8f3a3 100644 --- a/application/views/attributes/form.php +++ b/application/views/attributes/form.php @@ -6,7 +6,7 @@
- lang->line('attributes_definition_name'), 'definition_name', array('class' => 'control-label col-xs-3')); ?> + lang->line('attributes_definition_name'), 'definition_name', array('class'=>'required control-label col-xs-3')); ?>
'definition_name', @@ -17,7 +17,7 @@
- lang->line('attributes_definition_type'), 'definition_type', array('class'=>'control-label col-xs-3')); ?> + lang->line('attributes_definition_type'), 'definition_type', array('class'=>'required control-label col-xs-3')); ?>
definition_type, DEFINITION_TYPES), 'id="definition_type" class="form-control"');?>
@@ -54,8 +54,8 @@
'definition_value', 'class'=>'form-control input-sm', 'id' => 'definition_value'));?> - - + +
@@ -83,10 +83,10 @@ $(document).ready(function() var definition_type = $("#definition_type option:selected").text(); if(definition_type == "DATE" || (definition_type == "GROUP" && !is_new) || definition_type == "DECIMAL") - { - $('#definition_type').prop("disabled",true); - } - else if(definition_type == "DROPDOWN") + { + $('#definition_type').prop("disabled",true); + } + else if(definition_type == "DROPDOWN" || definition_type == "CHECKBOX") { $("#definition_type option:contains('GROUP')").hide(); $("#definition_type option:contains('DATE')").hide(); @@ -98,7 +98,7 @@ $(document).ready(function() } } disable_definition_types(); - + var show_hide_fields = function(event) { var is_dropdown = $('#definition_type').val() !== '1'; @@ -221,4 +221,4 @@ $(document).ready(function() } }, form_support.error)); }); - + \ No newline at end of file diff --git a/application/views/attributes/item.php b/application/views/attributes/item.php index 581741808..9919d4a4e 100644 --- a/application/views/attributes/item.php +++ b/application/views/attributes/item.php @@ -1,9 +1,8 @@ -
lang->line("attributes_definition_name"), "definition_name_label", array('class' => 'control-label col-xs-3')); ?> -
+
'definition_name', 'class' => 'form-control')); ?> -
+
@@ -13,44 +12,63 @@ foreach($definition_values as $definition_id => $definition_value) ?>
- 'control-label col-xs-3')); ?> -
-
+ 'control-label col-xs-3')); ?> +
+
+ attribute_date)) ? NOW : strtotime($attribute_value->attribute_date); + echo form_input(array( + 'name' => "attribute_links[$definition_id]", + 'value' => to_date($value), + 'class' => 'form-control input-sm datetime', + 'data-definition-id' => $definition_id, + 'readonly' => 'true')); + } + else if ($definition_value['definition_type'] == DROPDOWN) + { + $selected_value = $definition_value['selected_value']; + echo form_dropdown("attribute_links[$definition_id]", $definition_value['values'], $selected_value, "class='form-control' data-definition-id='$definition_id'"); + } + else if ($definition_value['definition_type'] == TEXT) + { + $value = (empty($attribute_value) || empty($attribute_value->attribute_value)) ? $definition_value['selected_value'] : $attribute_value->attribute_value; + echo form_input("attribute_links[$definition_id]", $value, "class='form-control valid_chars' data-definition-id='$definition_id'"); + } + else if ($definition_value['definition_type'] == DECIMAL) + { + $value = (empty($attribute_value) || empty($attribute_value->attribute_decimal)) ? $definition_value['selected_value'] : $attribute_value->attribute_decimal; + echo form_input("attribute_links[$definition_id]", $value, "class='form-control valid_chars' data-definition-id='$definition_id'"); + } + else if ($definition_value['definition_type'] == CHECKBOX) + { + $value = (empty($attribute_value) || empty($attribute_value->attribute_value)) ? $definition_value['selected_value'] : $attribute_value->attribute_value; - echo form_hidden("attribute_ids[$definition_id]", $definition_value['attribute_id']); - $attribute_value = $definition_value['attribute_value']; - - if ($definition_value['definition_type'] == DATE) - { - $value = (empty($attribute_value) || empty($attribute_value->attribute_date)) ? NOW : strtotime($attribute_value->attribute_date); - echo form_input(array( - 'name' => "attribute_links[$definition_id]", - 'value' => to_date($value), - 'class' => 'form-control input-sm datetime', - 'data-definition-id' => $definition_id, - 'readonly' => 'true')); - } - else if ($definition_value['definition_type'] == DROPDOWN) - { - $selected_value = $definition_value['selected_value']; - echo form_dropdown("attribute_links[$definition_id]", $definition_value['values'], $selected_value, "class='form-control' data-definition-id='$definition_id'"); - } - else if ($definition_value['definition_type'] == TEXT) - { - $value = (empty($attribute_value) || empty($attribute_value->attribute_value)) ? $definition_value['selected_value'] : $attribute_value->attribute_value; - echo form_input("attribute_links[$definition_id]", $value, "class='form-control valid_chars' data-definition-id='$definition_id'"); - } - else if ($definition_value['definition_type'] == DECIMAL) - { - $value = (empty($attribute_value) || empty($attribute_value->attribute_decimal)) ? $definition_value['selected_value'] : $attribute_value->attribute_decimal; - echo form_input("attribute_links[$definition_id]", $value, "class='form-control valid_chars' data-definition-id='$definition_id'"); - } - ?> - -
-
+ //Sends 0 if the box is unchecked instead of not sending anything. + echo form_input(array( + 'type' => 'hidden', + 'name' => "attribute_links[$definition_id]", + 'id' => "attribute_links[$definition_id]", + 'value' => 0, + 'data-definition-id' => $definition_id + )); + echo form_checkbox(array( + 'name' => "attribute_links[$definition_id]", + 'id' => "attribute_links[$definition_id]", + 'value' => 1, + 'checked' => ($value ? 1 : 0), + 'class' => 'checkbox-inline', + 'data-definition-id' => $definition_id + )); + } + ?> + +
+
$definition_value) ?> \ No newline at end of file