diff --git a/application/config/autoload.php b/application/config/autoload.php index a7b554177..d6a82548b 100644 --- a/application/config/autoload.php +++ b/application/config/autoload.php @@ -132,4 +132,4 @@ $autoload['language'] = array(); | | $autoload['model'] = array('first_model' => 'first'); */ -$autoload['model'] = array('Appconfig', 'Person', 'Customer', 'Employee', 'Module', 'Item', 'Item_taxes', 'Sale', 'Supplier', 'Inventory', 'Receiving', 'Giftcard', 'Item_kit', 'Item_kit_items', 'Stock_location', 'Item_quantity', 'Dinner_table', 'Customer_rewards', 'Rewards', 'Tax', 'Expense_category', 'Expense', 'Cashup'); +$autoload['model'] = array('Appconfig', 'Person', 'Customer', 'Employee', 'Module', 'Item', 'Item_taxes', 'Sale', 'Supplier', 'Inventory', 'Receiving', 'Giftcard', 'Item_kit', 'Item_kit_items', 'Stock_location', 'Item_quantity', 'Dinner_table', 'Customer_rewards', 'Rewards', 'Tax', 'Expense_category', 'Expense', 'Cashup', 'Attribute'); diff --git a/application/controllers/Attributes.php b/application/controllers/Attributes.php new file mode 100644 index 000000000..e7557cd55 --- /dev/null +++ b/application/controllers/Attributes.php @@ -0,0 +1,195 @@ +xss_clean(get_attribute_definition_manage_table_headers()); + + $this->load->view('attributes/manage', $data); + } + + /* + Returns customer table data rows. This will be called with AJAX. + */ + public function search() + { + $search = $this->input->get('search'); + $limit = $this->input->get('limit'); + $offset = $this->input->get('offset'); + $sort = $this->input->get('sort'); + $order = $this->input->get('order'); + + $attributes = $this->Attribute->search($search, $limit, $offset, $sort, $order); + $total_rows = $this->Attribute->get_found_rows($search); + + $data_rows = array(); + foreach($attributes->result() as $attribute) + { + $attribute->definition_flags = $this->_get_attributes($attribute->definition_flags); + $data_rows[] = get_attribute_definition_data_row($attribute, $this); + } + + $data_rows = $this->xss_clean($data_rows); + + echo json_encode(array('total' => $total_rows, 'rows' => $data_rows)); + } + + public function save_attribute_link($item_id) + { + if (!empty($this->input->post('attribute_id'))) + { + $success = $this->Attribute->save_link($item_id, $this->input->post('definition_id'), $this->input->post('attribute_id')); + } + else + { + $success = $this->Attribute->set_selected_category($item_id, $this->input->post('definition_id')); + } + + echo json_encode(array('success' => $success)); + } + + public function delete_attribute_link($item_id) + { + $success = $this->Attribute->delete_link($item_id); + + echo json_encode(array('success' => $success)); + } + + public function save_attribute_value($attribute_value) + { + $success = $this->Attribute->save_value($attribute_value, $this->input->post('definition_id'), $this->input->post('item_id'), $this->input->post('attribute_id')); + + echo json_encode(array('success' => $success)); + } + + public function delete_attribute_value($attribute_value) + { + $success = $this->Attribute->delete_value($attribute_value, $this->input->post('$definition_id')); + + echo json_encode(array('success' => $success)); + } + + public function save_definition($definition_id = -1) + { + $definition_flags = 0; + foreach($this->input->post('definition_flags') as $flag) + { + $definition_flags |= $flag; + } + + //Save definition data + $definition_data = array( + 'definition_name' => $this->input->post('definition_name'), + 'definition_type' => DEFINITION_TYPES[$this->input->post('definition_type')], + 'definition_flags' => $definition_flags, + 'definition_fk' => $this->input->post('definition_parent') != '' ? $this->input->post('definition_parent') : NULL + ); + + $definition_name = $this->xss_clean($definition_data['definition_name']); + + if($this->Attribute->save_definition($definition_data, $definition_id)) + { + //New definition + if($definition_id == -1) + { + $definition_values = json_decode($this->input->post('definition_values')); + + foreach($definition_values as $definition_value) + { + $this->Attribute->save_value($definition_value, $definition_data['definition_id']); + } + + echo json_encode(array('success' => TRUE, 'message' => $this->lang->line('attributes_definition_successful_adding').' '. + $definition_name, 'id' => $definition_data['definition_id'])); + } + else //Existing definition + { + echo json_encode(array('success' => TRUE, 'message' => $this->lang->line('attributes_definition_successful_updating').' '. + $definition_name, 'id' => $definition_id)); + } + } + else//failure + { + echo json_encode(array('success' => FALSE, 'message' => $this->lang->line('attribute_definitions_error_adding_updating').' '. + $definition_name, 'id' => -1)); + } + } + + public function suggest_attribute($definition_id) + { + $suggestions = $this->xss_clean($this->Attribute->get_suggestions($definition_id, $this->input->get('term'))); + + echo json_encode($suggestions); + } + + public function get_row($row_id) + { + $attribute_definition_info = $this->Attribute->get_info($row_id); + $attribute_definition_info->definition_flags = $this->_get_attributes($attribute_definition_info->definition_flags); + $data_row = $this->xss_clean(get_attribute_definition_data_row($attribute_definition_info)); + + echo json_encode($data_row); + } + + private function _get_attributes($definition_flags = 0) + { + $definition_flag_names = array(); + foreach (Attribute::get_definition_flags() as $id => $term) + { + if (empty($definition_flags) || ($id & $definition_flags)) + { + $definition_flag_names[$id] = $this->lang->line('attributes_' . strtolower($term) . '_visibility'); + } + } + return $definition_flag_names; + } + + public function view($definition_id = -1) + { + $info = $this->Attribute->get_info($definition_id); + foreach(get_object_vars($info) as $property => $value) + { + $info->$property = $this->xss_clean($value); + } + + $data['definition_id'] = $definition_id; + $data['definition_values'] = $this->Attribute->get_definition_values($definition_id); + $data['definition_parent'] = $this->Attribute->get_definitions_by_type(CATEGORY, $definition_id); + $data['definition_parent'][''] = $this->lang->line('common_none_selected_text'); + $data['definition_info'] = $info; + + $data['definition_flags'] = $this->_get_attributes(); + $data['selected_definition_flags'] = $this->_get_attributes($info->definition_flags); + + $this->load->view("attributes/form", $data); + } + + public function delete_value($attribute_id) + { + return $this->Attribute->delete_value($attribute_id); + } + + public function delete() + { + $attributes_to_delete = $this->input->post('ids'); + + if($this->Attribute->delete_definition_list($attributes_to_delete)) + { + $message = $this->lang->line('attributes_definition_successful_deleted') . ' ' . count($attributes_to_delete) . ' ' . $this->lang->line('attributes_definition_one_or_multiple'); + echo json_encode(array('success' => TRUE, 'message' => $message)); + } + else + { + 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/Config.php b/application/controllers/Config.php index 6bc838c7e..72855b6a1 100644 --- a/application/controllers/Config.php +++ b/application/controllers/Config.php @@ -299,18 +299,8 @@ class Config extends Secure_Controller 'suggestions_second_column' => $this->input->post('suggestions_second_column'), 'suggestions_third_column' => $this->input->post('suggestions_third_column'), 'giftcard_number' => $this->input->post('giftcard_number'), - 'derive_sale_quantity' => $this->input->post('derive_sale_quantity') != NULL, + 'derive_sale_quantity' => $this->input->post('derive_sale_quantity') != NULL 'multi_pack_enabled' => $this->input->post('multi_pack_enabled') != NULL, - 'custom1_name' => $this->input->post('custom1_name'), - 'custom2_name' => $this->input->post('custom2_name'), - 'custom3_name' => $this->input->post('custom3_name'), - 'custom4_name' => $this->input->post('custom4_name'), - 'custom5_name' => $this->input->post('custom5_name'), - 'custom6_name' => $this->input->post('custom6_name'), - 'custom7_name' => $this->input->post('custom7_name'), - 'custom8_name' => $this->input->post('custom8_name'), - 'custom9_name' => $this->input->post('custom9_name'), - 'custom10_name' => $this->input->post('custom10_name') ); $this->Module->set_show_office_group($this->input->post('show_office_group') != NULL); diff --git a/application/controllers/Items.php b/application/controllers/Items.php index 6a5395fb8..b445eedf7 100644 --- a/application/controllers/Items.php +++ b/application/controllers/Items.php @@ -25,7 +25,7 @@ class Items extends Secure_Controller 'low_inventory' => $this->lang->line('items_low_inventory_items'), 'is_serialized' => $this->lang->line('items_serialized_items'), 'no_description' => $this->lang->line('items_no_description_items'), - 'search_custom' => $this->lang->line('items_search_custom_items'), + 'search_custom' => $this->lang->line('items_search_attributes'), 'is_deleted' => $this->lang->line('items_is_deleted'), 'temporary' => $this->lang->line('items_temp')); @@ -164,16 +164,6 @@ class Items extends Secure_Controller echo json_encode($suggestions); } - - /* - Gives search suggestions based on what is being searched for - */ - public function suggest_custom() - { - $suggestions = $this->xss_clean($this->Item->get_custom_suggestions($this->input->post('term'), $this->input->post('field_no'))); - - echo json_encode($suggestions); - } public function get_row($item_ids) { @@ -201,6 +191,12 @@ class Items extends Secure_Controller $data['default_tax_1_rate'] = ''; $data['default_tax_2_rate'] = ''; $data['item_kits_enabled'] = $this->Employee->has_grant('item_kits', $this->Employee->get_logged_in_employee_info()->person_id); + $data['definition_values'] = $this->Attribute->get_attributes_by_item($item_id); + $categories = array(-1 => $this->lang->line('common_none_selected_text')); + $categories = $categories + $this->Attribute->get_definitions_by_type(CATEGORY); + $selected_category = $this->Attribute->get_selected_category($item_id); + $data['selected_category'] = empty($selected_category) ? NULL : $selected_category->definition_id; + $data['categories'] = $categories; $item_info = $this->Item->get_info($item_id); foreach(get_object_vars($item_info) as $property => $value) @@ -235,6 +231,7 @@ class Items extends Secure_Controller $item_info->receiving_quantity = 1; $item_info->reorder_level = 1; $item_info->item_type = ITEM; // standard + $item_info->item_id = $item_id; $item_info->stock_type = HAS_STOCK; $item_info->tax_category_id = 1; // Standard $item_info->qty_per_pack = 1; @@ -389,6 +386,13 @@ class Items extends Secure_Controller $this->load->view('barcodes/barcode_sheet', $data); } + public function attributes($item_id, $definition_id) + { + $data['item_id'] = $item_id; + $data['definition_values'] = $this->Attribute->get_values_by_parent($definition_id); + $this->load->view('attributes/item', $data); + } + public function bulk_edit() { $suppliers = array('' => $this->lang->line('items_none')); @@ -444,17 +448,7 @@ class Items extends Secure_Controller 'qty_per_pack' => $this->input->post('qty_per_pack') == NULL ? 1 : $this->input->post('qty_per_pack'), 'pack_name' => $this->input->post('pack_name') == NULL ? $default_pack_name : $this->input->post('pack_name'), 'low_sell_item_id' => $this->input->post('low_sell_item_id') == NULL ? -1 : $this->input->post('low_sell_item_id'), - 'deleted' => $this->input->post('is_deleted') != NULL, - 'custom1' => $this->input->post('custom1') == NULL ? '' : $this->input->post('custom1'), - 'custom2' => $this->input->post('custom2') == NULL ? '' : $this->input->post('custom2'), - 'custom3' => $this->input->post('custom3') == NULL ? '' : $this->input->post('custom3'), - 'custom4' => $this->input->post('custom4') == NULL ? '' : $this->input->post('custom4'), - 'custom5' => $this->input->post('custom5') == NULL ? '' : $this->input->post('custom5'), - 'custom6' => $this->input->post('custom6') == NULL ? '' : $this->input->post('custom6'), - 'custom7' => $this->input->post('custom7') == NULL ? '' : $this->input->post('custom7'), - 'custom8' => $this->input->post('custom8') == NULL ? '' : $this->input->post('custom8'), - 'custom9' => $this->input->post('custom9') == NULL ? '' : $this->input->post('custom9'), - 'custom10' => $this->input->post('custom10') == NULL ? '' : $this->input->post('custom10') + 'deleted' => $this->input->post('is_deleted') != NULL ); if($item_data['item_type'] == ITEM_TEMP) @@ -748,8 +742,7 @@ class Items extends Secure_Controller // XSS file data sanity check $data = $this->xss_clean($data); - /* haven't touched this so old templates will work, or so I guess... */ - if(sizeof($data) >= 23) + if(sizeof($data) >= 18) { $item_data = array( 'name' => $data[1], @@ -760,17 +753,7 @@ class Items extends Secure_Controller 'reorder_level' => $data[10], 'supplier_id' => $this->Supplier->exists($data[3]) ? $data[3] : NULL, 'allow_alt_description' => $data[12] != '' ? '1' : '0', - 'is_serialized' => $data[13] != '' ? '1' : '0', - 'custom1' => $data[14], - 'custom2' => $data[15], - 'custom3' => $data[16], - 'custom4' => $data[17], - 'custom5' => $data[18], - 'custom6' => $data[19], - 'custom7' => $data[20], - 'custom8' => $data[21], - 'custom9' => $data[22], - 'custom10' => $data[23] + 'is_serialized' => $data[13] != '' ? '1' : '0' ); /* we could do something like this, however, the effectiveness of @@ -778,7 +761,7 @@ class Items extends Secure_Controller into that directory, so you really can do whatever you want, this probably needs further discussion */ - $pic_file = $data[24]; + $pic_file = $data[19]; /*if(strcmp('.htaccess', $pic_file)==0) { $pic_file=''; diff --git a/application/helpers/tabular_helper.php b/application/helpers/tabular_helper.php index 770037081..041115e5e 100644 --- a/application/helpers/tabular_helper.php +++ b/application/helpers/tabular_helper.php @@ -523,6 +523,36 @@ function get_item_kit_data_row($item_kit) )); } +function get_attribute_definition_manage_table_headers() +{ + $CI =& get_instance(); + + $headers = array( + array('definition_id' => $CI->lang->line('attributes_definition_id')), + array('definition_name' => $CI->lang->line('attributes_definition_name')), + array('definition_type' => $CI->lang->line('attributes_definition_type')), + array('definition_flags' => $CI->lang->line('attributes_definition_flags')), + array('category' => $CI->lang->line('attributes_category')), + ); + + return transform_headers($headers); +} + +function get_attribute_definition_data_row($attribute) +{ + $CI =& get_instance(); + $controller_name=strtolower(get_class($CI)); + + return array ( + 'definition_id' => $attribute->definition_id, + 'definition_name' => $attribute->definition_name, + 'definition_type' => $attribute->definition_type, + 'category' => $attribute->parent_name, + 'definition_flags' => count($attribute->definition_flags) == 0 ? $CI->lang->line('common_none_selected_text') : implode(', ', $attribute->definition_flags), + 'edit' => anchor("$controller_name/view/$attribute->definition_id", '', + array('class'=>'modal-dlg', 'data-btn-submit' => $CI->lang->line('common_submit'), 'title'=>$CI->lang->line($controller_name.'_update')) + )); +} /* Get the header for the expense categories tabular view diff --git a/application/language/ar-EG/attributes_lang.php b/application/language/ar-EG/attributes_lang.php new file mode 100644 index 000000000..00229b05e --- /dev/null +++ b/application/language/ar-EG/attributes_lang.php @@ -0,0 +1,25 @@ +CI->session->unset_userdata('recv_stock_destination'); } - public function add_item($item_id, $quantity = 1, $item_location = NULL, $discount_type = 0, $discount = 0, $price = NULL, $description = NULL, $serialnumber = NULL, $receiving_quantity = NULL, $include_deleted = FALSE) + public function add_item($item_id, $quantity = 1, $item_location = NULL, $discount_type = 0, $discount = 0, $price = NULL, $description = NULL, $serialnumber = NULL, $receiving_quantity = NULL, $receiving_id = NULL, $include_deleted = FALSE) { //make sure item exists in database. if(!$this->CI->Item->exists($item_id, $include_deleted)) @@ -240,6 +240,7 @@ class Receiving_lib 'name' => $item_info->name, 'description' => $description != NULL ? $description: $item_info->description, 'serialnumber' => $serialnumber != NULL ? $serialnumber: '', + 'attribute_values' => $this->CI->Attribute->get_link_values($item_id, 'receiving_id', $receiving_id, Attribute::SHOW_IN_RECEIVINGS)->attribute_values, 'allow_alt_description' => $item_info->allow_alt_description, 'is_serialized' => $item_info->is_serialized, 'quantity' => $quantity, @@ -319,7 +320,7 @@ class Receiving_lib foreach($this->CI->Receiving->get_receiving_items($receiving_id)->result() as $row) { - $this->add_item($row->item_id, -$row->quantity_purchased, $row->item_location, $row->discount_type, $row->discount, $row->item_unit_price, $row->description, $row->serialnumber, $row->receiving_quantity, TRUE); + $this->add_item($row->item_id, -$row->quantity_purchased, $row->item_location, $row->discount_type, $row->discount, $row->item_unit_price, $row->description, $row->serialnumber, $receiving_id, $row->receiving_quantity, TRUE); } $this->set_supplier($this->CI->Receiving->get_supplier($receiving_id)->person_id); @@ -344,7 +345,7 @@ class Receiving_lib foreach($this->CI->Receiving->get_receiving_items($receiving_id)->result() as $row) { - $this->add_item($row->item_id, $row->quantity_purchased, $row->item_location, $row->discount_type, $row->discount, $row->item_unit_price, $row->description, $row->serialnumber, $row->receiving_quantity, TRUE); + $this->add_item($row->item_id, $row->quantity_purchased, $row->item_location, $row->discount_type, $row->discount, $row->item_unit_price, $row->description, $row->serialnumber, $row->receiving_quantity, $receiving_id, TRUE); } $this->set_supplier($this->CI->Receiving->get_supplier($receiving_id)->person_id); diff --git a/application/libraries/Sale_lib.php b/application/libraries/Sale_lib.php index 8ecd6fcb3..5db5b995d 100644 --- a/application/libraries/Sale_lib.php +++ b/application/libraries/Sale_lib.php @@ -696,10 +696,9 @@ class Sale_lib $this->CI->session->unset_userdata('sales_rewards_remainder'); } - public function add_item(&$item_id, $quantity = 1, $item_location, $discount = 0, $discount_type = 0, $price_mode = PRICE_MODE_STANDARD, $kit_price_option = NULL, $kit_print_option = NULL, $price_override = NULL, $description = NULL, $serialnumber = NULL, $include_deleted = FALSE, $print_option = NULL ) + public function add_item(&$item_id, $quantity = 1, $item_location, $discount = 0, $discount_type = 0, $price_mode = PRICE_MODE_STANDARD, $kit_price_option = NULL, $kit_print_option = NULL, $price_override = NULL, $description = NULL, $serialnumber = NULL, $sale_id = NULL, $include_deleted = FALSE, $print_option = NULL ) { $item_info = $this->CI->Item->get_info_by_id_or_number($item_id, $include_deleted); - //make sure item exists if(empty($item_info)) { @@ -844,6 +843,7 @@ class Sale_lib 'line' => $insertkey, 'name' => $item_info->name, 'item_number' => $item_info->item_number, + 'attribute_values' => $this->CI->Attribute->get_link_values($item_id, 'sale_id', $sale_id, Attribute::SHOW_IN_SALES)->attribute_values, 'description' => $description != NULL ? $description : $item_info->description, 'serialnumber' => $serialnumber != NULL ? $serialnumber : '', 'allow_alt_description' => $item_info->allow_alt_description, @@ -1019,7 +1019,7 @@ class Sale_lib foreach($this->CI->Sale->get_sale_items_ordered($sale_id)->result() as $row) { - $this->add_item($row->item_id, $row->quantity_purchased, $row->item_location, $row->discount, $row->discount_type, PRICE_MODE_STANDARD, NULL, NULL, $row->item_unit_price, $row->description, $row->serialnumber, TRUE, $row->print_option); + $this->add_item($row->item_id, $row->quantity_purchased, $row->item_location, $row->discount, $row->discount_type, PRICE_MODE_STANDARD, NULL, NULL, $row->item_unit_price, $row->description, $row->serialnumber, $sale_id, TRUE, $row->print_option); } foreach($this->CI->Sale->get_sale_payments($sale_id)->result() as $row) @@ -1047,7 +1047,7 @@ class Sale_lib $this->empty_cart(); foreach($this->CI->Sale->get_sale_items_ordered($sale_id)->result() as $row) { - $this->add_item($row->item_id, $row->quantity_purchased, $row->item_location, $row->discount, $row->discount_type, PRICE_MODE_STANDARD, NULL, NULL, $row->item_unit_price, $row->description, $row->serialnumber, TRUE, $row->print_option); + $this->add_item($row->item_id, $row->quantity_purchased, $row->item_location, $row->discount, $row->discount_type, PRICE_MODE_STANDARD, NULL, NULL, $row->item_unit_price, $row->description, $row->serialnumber, $sale_id, TRUE, $row->print_option); } return $this->CI->session->userdata('sales_cart'); diff --git a/application/migrations/20180220100000_attributes.php b/application/migrations/20180220100000_attributes.php new file mode 100644 index 000000000..521e7b15d --- /dev/null +++ b/application/migrations/20180220100000_attributes.php @@ -0,0 +1,20 @@ + diff --git a/application/migrations/sqlscripts/attributes.sql b/application/migrations/sqlscripts/attributes.sql new file mode 100644 index 000000000..35e8d6ba1 --- /dev/null +++ b/application/migrations/sqlscripts/attributes.sql @@ -0,0 +1,184 @@ + +CREATE TABLE IF NOT EXISTS `ospos_attribute_definitions` ( + `definition_id` INT(10) NOT NULL AUTO_INCREMENT, + `definition_name` VARCHAR(255) NOT NULL, + `definition_type` VARCHAR(45) NOT NULL, + `definition_flags` TINYINT(4) NOT NULL, + `definition_fk` INT(10) NULL, + `deleted` TINYINT(1) NOT NULL DEFAULT 0, + PRIMARY KEY (`definition_id`), + KEY `definition_fk` (`definition_fk`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +CREATE TABLE IF NOT EXISTS `ospos_attribute_values` ( + `attribute_id` INT NOT NULL AUTO_INCREMENT, + `attribute_value` VARCHAR(45) NULL, + PRIMARY KEY (`attribute_id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8; + + +CREATE TABLE IF NOT EXISTS `ospos_attribute_links` ( + `attribute_id` INT NULL, + `definition_id` INT NOT NULL, + `item_id` INT NULL, + `sale_id` INT NULL, + `receiving_id` INT NULL, + KEY `attribute_id` (`attribute_id`), + KEY `definition_id` (`definition_id`), + KEY `item_id` (`item_id`), + KEY `sale_id` (`sale_id`), + KEY `receiving_id` (`receiving_id`), + UNIQUE `attribute_links_uq1` (`attribute_id`, `definition_id`, `item_id`, `sale_id`, `receiving_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +ALTER TABLE `ospos_attribute_definitions` + ADD CONSTRAINT `fk_ospos_attribute_definitions_ibfk_1` FOREIGN KEY (`definition_fk`) REFERENCES `ospos_attribute_definitions` (`definition_id`); + + +ALTER TABLE `ospos_attribute_links` + ADD CONSTRAINT `ospos_attribute_links_ibfk_1` FOREIGN KEY (`definition_id`) REFERENCES `ospos_attribute_definitions` (`definition_id`) ON DELETE CASCADE, + ADD CONSTRAINT `ospos_attribute_links_ibfk_2` FOREIGN KEY (`attribute_id`) REFERENCES `ospos_attribute_values` (`attribute_id`) ON DELETE CASCADE, + ADD CONSTRAINT `ospos_attribute_links_ibfk_3` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`), + ADD CONSTRAINT `ospos_attribute_links_ibfk_4` FOREIGN KEY (`receiving_id`) REFERENCES `ospos_receivings` (`receiving_id`), + ADD CONSTRAINT `ospos_attribute_links_ibfk_5` FOREIGN KEY (`sale_id`) REFERENCES `ospos_sales` (`sale_id`); + + +UPDATE `ospos_modules` SET `sort` = 120 WHERE `name_lang_key` = 'module_config'; + +INSERT INTO `ospos_modules` (`name_lang_key`, `desc_lang_key`, `sort`, `module_id`) VALUES + ('module_attributes', 'module_attributes_desc', 110, 'attributes'); + +INSERT INTO `ospos_permissions` (`permission_id`, `module_id`) VALUES + ('attributes', 'attributes'); + +INSERT INTO `ospos_grants` (`permission_id`, `person_id`, `menu_group`) VALUES + ('attributes', 1, 'office'); + +-- migrate custom fields to text attributes +-- NOTE: items with custom attributes won't keep their selected category!! +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom1_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom2_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom3_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom4_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom5_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom6_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom7_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom8_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom9_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom10_name'; + +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom1_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom1 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom2_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom2 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom3_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom3 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom4_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom4 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom5_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom5 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom6_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom6 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom7_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom7 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom8_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom8 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom9_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom9 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom10_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom10 IS NOT NULL; + +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom1 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom2 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom3 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom4 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom5 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom6 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom7 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom8 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom9 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom10 FROM ospos_items; + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom1 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom1_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom2 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom2_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom3 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom3_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom4 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom4_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom5 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom5_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom6 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom6_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom7 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom7_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom8 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom8_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom9 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom9_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom10 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom10_name')); + +ALTER TABLE `ospos_items` + DROP COLUMN `custom1`, + DROP COLUMN `custom2`, + DROP COLUMN `custom3`, + DROP COLUMN `custom4`, + DROP COLUMN `custom5`, + DROP COLUMN `custom6`, + DROP COLUMN `custom7`, + DROP COLUMN `custom8`, + DROP COLUMN `custom9`, + DROP COLUMN `custom10`; \ No newline at end of file diff --git a/application/models/Attribute.php b/application/models/Attribute.php new file mode 100644 index 000000000..a8975a1a8 --- /dev/null +++ b/application/models/Attribute.php @@ -0,0 +1,408 @@ +getConstants()); + } + + /* + Determines if a given definition_id is an attribute + */ + public function exists($definition_id, $deleted = FALSE) + { + $this->db->from('attribute_definitions'); + $this->db->where('definition_id', $definition_id); + $this->db->where('deleted', $deleted); + + return ($this->db->get()->num_rows() == 1); + } + + public function link_exists($item_id, $definition_id = FALSE) + { + $this->db->where('sale_id'); + $this->db->where('receiving_id'); + $this->db->from('attribute_links'); + if (empty($definition_id)) + { + $this->db->where('definition_id <>'); + $this->db->where('attribute_id'); + } + else + { + $this->db->where('definition_id', $definition_id); + + } + $this->db->where('item_id', $item_id); + return $this->db->get()->num_rows() > 0; + } + + /* + Gets information about a particular attribute definition + */ + public function get_info($definition_id) + { + $this->db->select('parent_definition.definition_name AS parent_name, definition.*'); + $this->db->from('attribute_definitions AS definition'); + $this->db->join('attribute_definitions AS parent_definition', 'parent_definition.definition_id = definition.definition_fk', 'left'); + $this->db->where('definition.definition_id', $definition_id); + + $query = $this->db->get(); + + if($query->num_rows() == 1) + { + return $query->row(); + } + else + { + //Get empty base parent object, as $item_id is NOT an item + $item_obj = new stdClass(); + + //Get all the fields from items table + foreach($this->db->list_fields('attribute_definitions') as $field) + { + $item_obj->$field = ''; + } + + return $item_obj; + } + } + + /* + Performs a search on attribute definitions + */ + public function search($search, $rows = 0, $limit_from = 0, $sort = 'definition.definition_name', $order = 'asc') + { + $this->db->select('parent_definition.definition_name AS parent_name, definition.*'); + $this->db->from('attribute_definitions AS definition'); + $this->db->join('attribute_definitions AS parent_definition', 'parent_definition.definition_id = definition.definition_fk', 'left'); + + $this->db->group_start(); + $this->db->like('definition.definition_name', $search); + $this->db->or_like('definition.definition_type', $search); + $this->db->group_end(); + $this->db->where('definition.deleted', 0); + $this->db->order_by($sort, $order); + + if($rows > 0) + { + $this->db->limit($rows, $limit_from); + } + + return $this->db->get(); + } + + public function get_attributes_by_item($item_id) + { + $this->db->from('attribute_definitions'); + $this->db->join('attribute_links', 'attribute_links.definition_id = attribute_definitions.definition_id'); + $this->db->where('item_id', $item_id); + $this->db->where('deleted', 0); + + return $this->db->get()->result_array(); + } + + public function get_values_by_parent($definition_fk) + { + $this->db->from('attribute_definitions'); + if ($definition_fk != -1) + { + $this->db->where('definition_fk', $definition_fk); + } + else + { + $this->db->where('definition_fk'); + } + $this->db->where('deleted', 0); + + return $this->db->get()->result_array(); + } + + public function get_definitions_by_type($attribute_type, $definition_id = -1) + { + $this->db->from('attribute_definitions'); + $this->db->where('definition_type', $attribute_type); + $this->db->where('deleted', 0); + + if ($definition_id != -1) + { + $this->db->where('definition_id != ', $definition_id); + } + + $this->db->where('definition_fk'); + $results = $this->db->get()->result_array(); + + $attribute_definitions = array(); + foreach($results as $result) + { + $attribute_definitions[$result['definition_id']] = $result['definition_name']; + } + return $attribute_definitions; + } + + public function get_definition_values($definition_id) + { + $attribute_values = []; + + if ($definition_id > -1) + { + $this->db->from('attribute_links'); + $this->db->join('attribute_values', 'attribute_values.attribute_id = attribute_links.attribute_id'); + $this->db->where('definition_id', $definition_id); + $this->db->where('item_id'); + + $results = $this->db->get()->result_array(); + + $attribute_definitions = array(); + foreach($results as $result) + { + $attribute_definitions[$result['attribute_id']] = $result['attribute_value']; + } + return $attribute_definitions; + } + return $attribute_values; + } + + /* + Gets total of rows + */ + public function get_total_rows() + { + $this->db->from('attribute_definitions'); + $this->db->where('deleted', 0); + + return $this->db->count_all_results(); + } + + /* + Get number of rows + */ + public function get_found_rows($search) + { + return $this->search($search)->num_rows(); + } + + /* + 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 + $this->db->trans_start(); + + if($definition_id === -1 || !$this->exists($definition_id)) + { + $success = $this->db->insert('attribute_definitions', $definition_data); + $definition_data['definition_id'] = $this->db->insert_id(); + } + else + { + $this->db->where('definition_id', $definition_id); + $success = $this->db->update('attribute_definitions', $definition_data); + $definition_data['definition_id'] = $definition_id; + } + + $this->db->trans_complete(); + + $success &= $this->db->trans_status(); + + return $success; + } + + public function get_definition_by_name($definition_name, $definition_type) + { + $this->db->from('attribute_definitions'); + $this->db->where('definition_name', $definition_name); + $this->db->where('definition_type', $definition_type); + return $this->db->get()->row_object(); + } + + public function save_link($item_id, $definition_id, $attribute_id) + { + $this->db->trans_start(); + if ($this->link_exists($item_id, $definition_id)) + { + $this->db->where('definition_id', $definition_id); + $this->db->where('item_id', $item_id); + $this->db->where('sale_id'); + $this->db->where('receiving_id'); + $this->db->update('attribute_links', array('attribute_id' => $attribute_id)); + } + else + { + $this->db->insert('attribute_links', array('attribute_id' => $attribute_id, 'item_id' => $item_id, 'definition_id' => $definition_id)); + } + + $this->db->trans_complete(); + return $this->db->trans_status(); + } + + public function delete_link($item_id) + { + $this->db->where('sale_id'); + $this->db->where('receiving_id'); + return $this->db->delete('attribute_links', array('item_id' => $item_id)); + } + + public function set_selected_category($item_id, $definition_id) + { + $this->db->trans_start(); + + if ($this->link_exists($item_id)) + { + $this->db->where('item_id', $item_id); + $this->db->where('attribute_id'); + $this->db->update('attribute_links', array('definition_id' => $definition_id)); + } + else + { + $this->db->insert('attribute_links', array('item_id' => $item_id, 'definition_id' => $definition_id)); + } + + $this->db->trans_complete(); + + return $this->db->trans_status(); + } + + public function get_selected_category($item_id) + { + $this->db->from('attribute_links'); + $this->db->join('attribute_definitions', 'attribute_definitions.definition_id = attribute_links.definition_id'); + $this->db->where('item_id', $item_id); + $this->db->where('definition_type', CATEGORY); + $this->db->where('definition_fk'); + return $this->db->get()->row(); + } + + public function get_link_value($item_id, $definition_id) + { + $this->db->where('item_id', $item_id); + $this->db->where('definition_id', $definition_id); + $this->db->where('sale_id'); + $this->db->where('receiving_id'); + return $this->db->get('attribute_links')->row_object(); + } + + public function get_link_values($item_id, $sale_receiving_fk, $id, $definition_flags) + { + $this->db->select('GROUP_CONCAT(attribute_value SEPARATOR ",") AS attribute_values'); + $this->db->from('attribute_links'); + $this->db->join('attribute_values', 'attribute_values.attribute_id = attribute_links.attribute_id'); + $this->db->join('attribute_definitions', 'attribute_definitions.definition_id = attribute_links.definition_id'); + $this->db->where('definition_type <>', CATEGORY); + if (!empty($id)) + { + $this->db->where($sale_receiving_fk, $id); + } + else + { + $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); + return $this->db->get()->row_object(); + } + + public function get_attribute_value($item_id, $definition_id) + { + $this->db->from('attribute_values'); + $this->db->join('attribute_links', 'attribute_links.attribute_id = attribute_values.attribute_id'); + $this->db->where('definition_id', $definition_id); + $this->db->where('sale_id'); + $this->db->where('receiving_id'); + $this->db->where('item_id', (int) $item_id); + return $this->db->get()->row_object(); + } + + public function copy_attribute_links($item_id, $sale_receiving_fk, $id) + { + $this->db->query( + 'INSERT INTO ospos_attribute_links (item_id, definition_id, attribute_id, ' . $sale_receiving_fk . ') + SELECT ' . $this->db->escape($item_id) . ', definition_id, attribute_id, ' . $this->db->escape($id) . ' + FROM ' . $this->db->dbprefix('attribute_links') . ' + WHERE item_id = ' . $this->db->escape($item_id) . ' AND sale_id IS NULL AND receiving_id IS NULL' + ); + } + + public function get_suggestions($definition_id, $term) + { + $suggestions = array(); + $this->db->distinct(); + $this->db->select('attribute_value'); + $this->db->from('attribute_definitions AS definition'); + $this->db->join('attribute_links', 'attribute_links.definition_id = definition.definition_id'); + $this->db->join('attribute_values', 'attribute_values.attribute_id = attribute_links.attribute_id'); + $this->db->like('attribute_value', $term); + $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; + $suggestions[] = array('label' => $row_array['attribute_value']); + } + + return $suggestions; + } + + public function save_value($attribute_value, $definition_id, $item_id = FALSE, $attribute_id = FALSE) + { + $this->db->trans_start(); + + if (empty($attribute_id) || empty($item_id)) + { + $this->db->insert('attribute_values', array('attribute_value' => $attribute_value)); + $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)); + } + else + { + $this->db->where('attribute_id', $attribute_id); + $this->db->update('attribute_values', array('attribute_value' => $attribute_value)); + } + + $this->db->trans_complete(); + + return $this->db->trans_status(); + } + + public function delete_value($attribute_value, $definition_id) + { + return $this->db->query("DELETE atrv, atrl FROM " . $this->db->dbprefix('attribute_values') . " atrv, " . $this->db->dbprefix('attribute_links') . " atrl " . + "WHERE atrl.attribute_id = atrv.attribute_id AND atrv.attribute_value = " . $this->db->escape($attribute_value) . " AND atrl.definition_id = " . $this->db->escape($definition_id)); + } + + public function delete_definition($definition_id) + { + $this->db->where('definition_id', $definition_id); + + return $this->db->update('attribute_definitions', array('deleted' => 1)); + } + + public function delete_definition_list($definition_ids) + { + $this->db->where_in('definition_id', $definition_ids); + + return $this->db->update('attribute_definitions', array('deleted' => 1)); + } + + +} \ No newline at end of file diff --git a/application/models/Item.php b/application/models/Item.php index ca324bdc3..e074dd75d 100644 --- a/application/models/Item.php +++ b/application/models/Item.php @@ -130,16 +130,6 @@ class Item extends CI_Model $this->db->select('MAX(items.is_serialized) AS is_serialized'); $this->db->select('MAX(items.pack_name) AS pack_name'); $this->db->select('MAX(items.deleted) AS deleted'); - $this->db->select('MAX(items.custom1) AS custom1'); - $this->db->select('MAX(items.custom2) AS custom2'); - $this->db->select('MAX(items.custom3) AS custom3'); - $this->db->select('MAX(items.custom4) AS custom4'); - $this->db->select('MAX(items.custom5) AS custom5'); - $this->db->select('MAX(items.custom6) AS custom6'); - $this->db->select('MAX(items.custom7) AS custom7'); - $this->db->select('MAX(items.custom8) AS custom8'); - $this->db->select('MAX(items.custom9) AS custom9'); - $this->db->select('MAX(items.custom10) AS custom10'); $this->db->select('MAX(suppliers.person_id) AS person_id'); $this->db->select('MAX(suppliers.company_name) AS company_name'); @@ -190,24 +180,15 @@ class Item extends CI_Model $this->db->like('name', $search); $this->db->or_like('item_number', $search); $this->db->or_like('items.item_id', $search); + $this->db->or_like('definition_name', $search); $this->db->or_like('company_name', $search); $this->db->or_like('items.category', $search); $this->db->group_end(); } else { - $this->db->group_start(); - $this->db->like('custom1', $search); - $this->db->or_like('custom2', $search); - $this->db->or_like('custom3', $search); - $this->db->or_like('custom4', $search); - $this->db->or_like('custom5', $search); - $this->db->or_like('custom6', $search); - $this->db->or_like('custom7', $search); - $this->db->or_like('custom8', $search); - $this->db->or_like('custom9', $search); - $this->db->or_like('custom10', $search); - $this->db->group_end(); + $this->db->join('attribute_values', 'attribute_links.attribute_id = attribute_values.attribute_id'); + $this->db->like('attribute_value', $search); } } @@ -380,18 +361,40 @@ class Item extends CI_Model return FALSE; } + private function create_temp_table() + { + $this->db->query('CREATE TEMPORARY TABLE IF NOT EXISTS ' . $this->db->dbprefix('item_categories') . + ' (PRIMARY KEY(item_id, sale_id, receiving_id, definition_id), INDEX(item_id, sale_id, receiving_id, definition_id)) + ( + SELECT definition_name AS category, definition_type, attribute_links.item_id, + sale_id, receiving_id, attribute_links.definition_id + FROM ' . $this->db->dbprefix('attribute_links') . ' AS attribute_links + INNER JOIN ' . $this->db->dbprefix('attribute_definitions') . ' AS attribute_definitions + ON attribute_definitions.definition_id = attribute_links.definition_id AND definition_type = \'CATEGORY\' + WHERE sale_id IS NULL AND receiving_id IS NULL + )' + ); + } + /* Gets information about multiple items */ public function get_multiple_info($item_ids, $location_id) { + $this->create_temp_table(); + + $this->db->select('items.*'); + $this->db->select('company_name'); + $this->db->select('category'); + $this->db->select('quantity'); $this->db->from('items'); $this->db->join('suppliers', 'suppliers.person_id = items.supplier_id', 'left'); $this->db->join('item_quantities', 'item_quantities.item_id = items.item_id', 'left'); + $this->db->join('item_categories', 'item_categories.item_id = items.item_id', 'left'); $this->db->where('location_id', $location_id); $this->db->where_in('items.item_id', $item_ids); - return $this->db->get(); + return $this->db->get(); } /* @@ -638,19 +641,11 @@ class Item extends CI_Model //Search by custom fields if($filters['search_custom'] != FALSE) { - $this->db->from('items'); - $this->db->group_start(); - $this->db->like('custom1', $search); - $this->db->or_like('custom2', $search); - $this->db->or_like('custom3', $search); - $this->db->or_like('custom4', $search); - $this->db->or_like('custom5', $search); - $this->db->or_like('custom6', $search); - $this->db->or_like('custom7', $search); - $this->db->or_like('custom8', $search); - $this->db->or_like('custom9', $search); - $this->db->or_like('custom10', $search); - $this->db->group_end(); + $this->db->from('attribute_links'); + $this->db->join('attribute_links.attribute_id = attribute_values.attribute_id'); + $this->db->join('attribute_definitions', 'attribute_definitions.definition_id = attribute_links.definition_id'); + $this->db->like('attribute_value', $search); + $this->db->where('definition_type', TEXT); $this->db->where('deleted', $filters['is_deleted']); $this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later foreach($this->db->get()->result() as $row) @@ -748,20 +743,11 @@ class Item extends CI_Model //Search by custom fields if($filters['search_custom'] != FALSE) { - $this->db->from('items'); - $this->db->group_start(); - $this->db->like('custom1', $search); - $this->db->or_like('custom2', $search); - $this->db->or_like('custom3', $search); - $this->db->or_like('custom4', $search); - $this->db->or_like('custom5', $search); - $this->db->or_like('custom6', $search); - $this->db->or_like('custom7', $search); - $this->db->or_like('custom8', $search); - $this->db->or_like('custom9', $search); - $this->db->or_like('custom10', $search); - $this->db->group_end(); - $this->db->where_in('item_type', $non_kit); // standard, exclude kit items since kits will be picked up later + $this->db->from('attribute_links'); + $this->db->join('attribute_links.attribute_id = attribute_values.attribute_id'); + $this->db->join('attribute_definitions', 'attribute_definitions.definition_id = attribute_links.definition_id'); + $this->db->like('attribute_value', $search); + $this->db->where('definition_type', TEXT); $this->db->where('stock_type', '0'); // stocked items only $this->db->where('deleted', $filters['is_deleted']); foreach($this->db->get()->result() as $row) @@ -937,24 +923,6 @@ class Item extends CI_Model return $suggestions; } - public function get_custom_suggestions($search, $field_no) - { - $suggestions = array(); - $this->db->distinct(); - $this->db->select('custom'.$field_no); - $this->db->from('items'); - $this->db->like('custom'.$field_no, $search); - $this->db->where('deleted', 0); - $this->db->order_by('custom'.$field_no, 'asc'); - foreach($this->db->get()->result() as $row) - { - $row_array = (array) $row; - $suggestions[] = array('label' => $row_array['custom'.$field_no]); - } - - return $suggestions; - } - public function get_categories() { $this->db->select('category'); diff --git a/application/models/Item_kit.php b/application/models/Item_kit.php index 06c3ed9dc..15e100cb1 100644 --- a/application/models/Item_kit.php +++ b/application/models/Item_kit.php @@ -62,7 +62,7 @@ class Item_kit extends CI_Model kit_discount_type, price_option, print_option, - category, + definition_name, supplier_id, item_number, cost_price, @@ -73,21 +73,13 @@ class Item_kit extends CI_Model allow_alt_description, is_serialized, items.deleted, - custom1, - custom2, - custom3, - custom4, - custom5, - custom6, - custom7, - custom8, - custom9, - custom10, item_type, stock_type'); $this->db->from('item_kits'); $this->db->join('items', 'item_kits.item_id = items.item_id', 'left'); + $this->db->join('attribute_links', 'attribute_links.item_id = items.item_id', 'left'); + $this->db->join('attribute_definitions', 'attribute_links.definition_id = attribute_definitions.definition_id AND definition_type = \'CATEGORY\'', 'left'); $this->db->where('item_kit_id', $item_kit_id); $query = $this->db->get(); diff --git a/application/models/Receiving.php b/application/models/Receiving.php index b9c87047a..02f87455c 100644 --- a/application/models/Receiving.php +++ b/application/models/Receiving.php @@ -59,7 +59,7 @@ class Receiving extends CI_Model return $this->db->update('receivings', $receiving_data); } - public function save($items, $supplier_id, $employee_id, $comment, $reference, $payment_type, $receiving_id = FALSE) + public function save($items, $supplier_id, $employee_id, $comment, $reference, $payment_type) { if(count($items) == 0) { @@ -127,6 +127,8 @@ class Receiving extends CI_Model $this->Inventory->insert($inv_data); + $this->Attribute->copy_attribute_links($item['item_id'], 'receiving_id', $receiving_id); + $supplier = $this->Supplier->get_info($supplier_id); } diff --git a/application/models/Sale.php b/application/models/Sale.php index 6a19f7fba..d23e45860 100644 --- a/application/models/Sale.php +++ b/application/models/Sale.php @@ -692,8 +692,10 @@ class Sale extends CI_Model $this->Inventory->insert($inv_data); } - // Calculate taxes and save the tax information for the sale. Return the result for printing + $this->Attribute->copy_attribute_links($item['item_id'], 'sale_id', $sale_id); + // Calculate taxes and save the tax information for the sale. Return the result for printing + $customer = $this->Customer->get_info($customer_id); if($customer_id == -1 || $customer->taxable) { if($this->config->item('tax_included')) @@ -935,14 +937,16 @@ class Sale extends CI_Model item_location, print_option, ' . $this->Item->get_item_name('name') . ', - category, + definition_name, item_type, stock_type'); $this->db->from('sales_items AS sales_items'); $this->db->join('items AS items', 'sales_items.item_id = items.item_id'); + $this->db->join('attribute_links', 'items.item_id = attribute_links.item_id AND sales_items.sale_id = attribute_links.sale_id', 'left'); + $this->db->join('attribute_definitions', 'attribute_definitions.definition_id = attribute_links.definition_id', 'left'); $this->db->where('sales_items.sale_id', $sale_id); - // Entry sequence (this will render kits in the expected sequence) + // Entry sequenate (this will render kits in the expected sequence) if($this->config->item('line_sequence') == '0') { $this->db->order_by('line', 'asc'); @@ -958,7 +962,7 @@ class Sale extends CI_Model // Group by Item Category elseif($this->config->item('line_sequence') == '2') { - $this->db->order_by('category', 'asc'); + $this->db->order_by('definition_name', 'asc'); $this->db->order_by('sales_items.description', 'asc'); $this->db->order_by('items.name', 'asc'); $this->db->order_by('items.qty_per_pack', 'asc'); @@ -1189,7 +1193,7 @@ class Sale extends CI_Model items.item_id AS item_id, MAX(' . $this->Item->get_item_name() . ') AS name, MAX(items.item_number) AS item_number, - MAX(items.category) AS category, + MAX(definition_name) AS category, MAX(items.supplier_id) AS supplier_id, MAX(sales_items.quantity_purchased) AS quantity_purchased, MAX(sales_items.item_cost_price) AS item_cost_price, @@ -1214,6 +1218,10 @@ class Sale extends CI_Model ON sales_items.sale_id = sales.sale_id INNER JOIN ' . $this->db->dbprefix('items') . ' AS items ON sales_items.item_id = items.item_id + LEFT OUTER JOIN ' . $this->db->dbprefix('attribute_links') . ' AS attribute_links + ON attribute_links.item_id = items.item_id AND attribute_links.sale_id = sales_items.sale_id + LEFT OUTER JOIN ' . $this->db->dbprefix('attribute_definitions') . ' AS attribute_definitions + ON attribute_definitions.definition_id = attribute_links.definition_id AND definition_type = \'CATEGORY\' LEFT OUTER JOIN ' . $this->db->dbprefix('sales_payments_temp') . ' AS payments ON sales_items.sale_id = payments.sale_id LEFT OUTER JOIN ' . $this->db->dbprefix('suppliers') . ' AS supplier diff --git a/application/models/reports/Detailed_receivings.php b/application/models/reports/Detailed_receivings.php index 695eb7498..c034e6962 100644 --- a/application/models/reports/Detailed_receivings.php +++ b/application/models/reports/Detailed_receivings.php @@ -97,10 +97,12 @@ class Detailed_receivings extends Report foreach($data['summary'] as $key=>$value) { - $this->db->select('name, item_number, category, quantity_purchased, serialnumber,total, discount, discount_type, item_location, receivings_items_temp.receiving_quantity'); + $this->db->select('name, item_number, category, quantity_purchased, serialnumber, total, discount, discount_type, item_location, receivings_items_temp.receiving_quantity'); $this->db->from('receivings_items_temp'); $this->db->join('items', 'receivings_items_temp.item_id = items.item_id'); - $this->db->where('receiving_id = '.$value['receiving_id']); + $this->db->join('attribute_links', 'attribute_links.item_id = items.item_id AND attribute_links.receiving_id = receivings_items_temp.receiving_id', 'left'); + $this->db->join('attribute_definitions', 'attribute_definitions.definition_id = attribute_links.definition_id AND definition_type = \'CATEGORY\'', 'left'); + $this->db->where('receivings_items_temp.receiving_id', $value['receiving_id']); $data['details'][$key] = $this->db->get()->result_array(); } diff --git a/application/views/attributes/form.php b/application/views/attributes/form.php new file mode 100644 index 000000000..14a902089 --- /dev/null +++ b/application/views/attributes/form.php @@ -0,0 +1,173 @@ +
lang->line('common_fields_required_message'); ?>
+ + + +'attribute_form', 'class'=>'form-horizontal')); ?> +
+ +
+ lang->line('attributes_definition_name'), 'definition_name', array('class' => 'control-label col-xs-3')); ?> +
+ 'definition_name', + 'class'=>'form-control input-sm', + 'value'=>$definition_info->definition_name) + );?> +
+
+ +
+ lang->line('attributes_definition_type'), 'definition_type', array('class'=>'control-label col-xs-3')); ?> +
+ definition_type == CATEGORY; ?> + definition_type, DEFINITION_TYPES), 'id="definition_type" class="form-control" ' . ($disable_definition_type ? 'disabled="disabled"' : ''));?> +
+
+ +
+ lang->line('attributes_category'), 'definition_parent', array('class' => 'control-label col-xs-3')); ?> +
+ definition_fk, 'id="definition_parent" class="form-control" ' . (empty($definition_parent) ? 'disabled="disabled"' : ''));?> +
+
+ + + + + + + +
+ + + \ No newline at end of file diff --git a/application/views/attributes/item.php b/application/views/attributes/item.php new file mode 100644 index 000000000..a3dad96e5 --- /dev/null +++ b/application/views/attributes/item.php @@ -0,0 +1,69 @@ + + +
+ 'control-label col-xs-3')); ?> +
+
+ + $definition_name, + 'value' => date($this->config->item('dateformat') . ' ' . $this->config->item('timeformat'), strtotime($definition_value['attribute_value'])), + 'class' => 'form-control input-sm', + 'data-definition-id' => $definition_value['definition_id'], + 'readonly' => 'true')); + } + else if ($definition_value['definition_type'] == DROPDOWN) + { + $values = $this->Attribute->get_definition_values($definition_id); + $selected_value = $this->Attribute->get_link_value($item_id, $definition_id); + echo form_dropdown($definition_name, $values, (empty($selected_value) ? NULL : $selected_value->attribute_id), "class='form-control' data-definition-id='$definition_id'"); + } + else if ($definition_value['definition_type'] == TEXT) + { + $attribute_value = $this->Attribute->get_attribute_value($item_id, $definition_id); + $value = (empty($attribute_value) || empty($attribute_value->attribute_value)) ? NULL : $attribute_value->attribute_value; + $id = (empty($attribute_value) || empty($attribute_value->attribute_id)) ? NULL : $attribute_value->attribute_id; + echo form_input($definition_name, $value, "class='form-control' data-attribute-id='$id'"); + } + ?> +
+
+
+ + + + diff --git a/application/views/attributes/manage.php b/application/views/attributes/manage.php new file mode 100644 index 000000000..d36f32bda --- /dev/null +++ b/application/views/attributes/manage.php @@ -0,0 +1,37 @@ +load->view("partial/header"); ?> + + + + + +
+ +
+ +
+
+
+ +load->view("partial/footer"); ?> diff --git a/application/views/configs/general_config.php b/application/views/configs/general_config.php index 129deabd7..a20fa2759 100644 --- a/application/views/configs/general_config.php +++ b/application/views/configs/general_config.php @@ -235,116 +235,6 @@ -
- lang->line('config_custom1'), 'config_custom1', array('class' => 'control-label col-xs-2')); ?> -
- 'custom1_name', - 'id' => 'custom1_name', - 'class' => 'form-control input-sm', - 'value' => $this->config->item('custom1_name'))); ?> -
-
- -
- lang->line('config_custom2'), 'config_custom2', array('class' => 'control-label col-xs-2')); ?> -
- 'custom2_name', - 'id' => 'custom2_name', - 'class' => 'form-control input-sm', - 'value' => $this->config->item('custom2_name'))); ?> -
-
- -
- lang->line('config_custom3'), 'config_custom3', array('class' => 'control-label col-xs-2')); ?> -
- 'custom3_name', - 'id' => 'custom3_name', - 'class' => 'form-control input-sm', - 'value' => $this->config->item('custom3_name'))); ?> -
-
- -
- lang->line('config_custom4'), 'config_custom4', array('class' => 'control-label col-xs-2')); ?> -
- 'custom4_name', - 'id' => 'custom4_name', - 'class' => 'form-control input-sm', - 'value' => $this->config->item('custom4_name'))); ?> -
-
- -
- lang->line('config_custom5'), 'config_custom5', array('class' => 'control-label col-xs-2')); ?> -
- 'custom5_name', - 'id' => 'custom5_name', - 'class' => 'form-control input-sm', - 'value' => $this->config->item('custom5_name'))); ?> -
-
- -
- lang->line('config_custom6'), 'config_custom6', array('class' => 'control-label col-xs-2')); ?> -
- 'custom6_name', - 'id' => 'custom6_name', - 'class' => 'form-control input-sm', - 'value' => $this->config->item('custom6_name'))); ?> -
-
- -
- lang->line('config_custom7'), 'config_custom7', array('class' => 'control-label col-xs-2')); ?> -
- 'custom7_name', - 'id' => 'custom7_name', - 'class' => 'form-control input-sm', - 'value' => $this->config->item('custom7_name'))); ?> -
-
- -
- lang->line('config_custom8'), 'config_custom8', array('class' => 'control-label col-xs-2')); ?> -
- 'custom8_name', - 'id' => 'custom8_name', - 'class' => 'form-control input-sm', - 'value' => $this->config->item('custom8_name'))); ?> -
-
- -
- lang->line('config_custom9'), 'config_custom9', array('class' => 'control-label col-xs-2')); ?> -
- 'custom9_name', - 'id' => 'custom9_name', - 'class' => 'form-control input-sm', - 'value' => $this->config->item('custom9_name'))); ?> -
-
- -
- lang->line('config_custom10'), 'config_custom10', array('class' => 'control-label col-xs-2')); ?> -
- 'custom10_name', - 'id' => 'custom10_name', - 'class' => 'form-control input-sm', - 'value' => $this->config->item('custom10_name'))); ?> -
-
-
lang->line('config_backup_database'), 'config_backup_database', array('class' => 'control-label col-xs-2')); ?>
diff --git a/application/views/items/form.php b/application/views/items/form.php index 66303fb80..eaa360773 100644 --- a/application/views/items/form.php +++ b/application/views/items/form.php @@ -46,6 +46,10 @@
+
+ load->view('attributes/item', array('item_id' => $item_info->item_id)); ?> +
+
lang->line('items_stock_type'), 'stock_type', !empty($basic_version) ? array('class'=>'required control-label col-xs-3') : array('class'=>'control-label col-xs-3')); ?> @@ -387,44 +391,20 @@
- - config->item('custom'.$i.'_name') != NULL) - { - $item_arr = (array)$item_info; - ?> -
- config->item('custom'.$i.'_name'), 'custom'.$i, array('class'=>'control-label col-xs-3')); ?> -
- 'custom'.$i, - 'id'=>'custom'.$i, - 'class'=>'form-control input-sm', - 'value'=>$item_arr['custom'.$i]) - );?> -
-
- + diff --git a/application/views/partial/header.php b/application/views/partial/header.php index 01767b8bd..b7533f8fb 100644 --- a/application/views/partial/header.php +++ b/application/views/partial/header.php @@ -77,7 +77,7 @@ - + @@ -120,7 +120,7 @@ - + @@ -141,4 +141,4 @@
- + diff --git a/application/views/receivings/receipt.php b/application/views/receivings/receipt.php index f28296538..6a87be2e6 100644 --- a/application/views/receivings/receipt.php +++ b/application/views/receivings/receipt.php @@ -78,7 +78,7 @@ { ?> - +    x diff --git a/application/views/receivings/receiving.php b/application/views/receivings/receiving.php index 516c472e3..9aa96cd6f 100644 --- a/application/views/receivings/receiving.php +++ b/application/views/receivings/receiving.php @@ -136,7 +136,7 @@ if (isset($success)) ');?> -
+
diff --git a/application/views/sales/invoice.php b/application/views/sales/invoice.php index 85ac25149..10c966700 100755 --- a/application/views/sales/invoice.php +++ b/application/views/sales/invoice.php @@ -129,7 +129,7 @@ $(document).ready(function() ?> - + diff --git a/application/views/sales/receipt_default.php b/application/views/sales/receipt_default.php index 4197e4985..9dca474ef 100644 --- a/application/views/sales/receipt_default.php +++ b/application/views/sales/receipt_default.php @@ -69,7 +69,7 @@ { ?> - + config->item('receipt_show_total_discount') ? 'total' : 'discounted_total')]); ?> diff --git a/application/views/sales/receipt_email.php b/application/views/sales/receipt_email.php index a3391193d..b1e1f67e0 100644 --- a/application/views/sales/receipt_email.php +++ b/application/views/sales/receipt_email.php @@ -64,7 +64,7 @@ { ?> - + config->item('receipt_show_total_discount') ? 'total' : 'discounted_total')]); ?> diff --git a/application/views/sales/receipt_short.php b/application/views/sales/receipt_short.php index 199bc894c..488ec532b 100644 --- a/application/views/sales/receipt_short.php +++ b/application/views/sales/receipt_short.php @@ -66,7 +66,7 @@ { ?> - + config->item('receipt_show_total_discount') ? 'total' : 'discounted_total')]); ?> diff --git a/application/views/sales/register.php b/application/views/sales/register.php index 7fde2d58c..760e1199f 100644 --- a/application/views/sales/register.php +++ b/application/views/sales/register.php @@ -156,7 +156,7 @@ if(isset($success)) ?> - +

diff --git a/bower.json b/bower.json index a8924473a..e6ab56739 100644 --- a/bower.json +++ b/bower.json @@ -46,6 +46,9 @@ "bootstrap-tagsinput": "~0.8.0", "bootstrap-toggle": "^2.2.2" }, + "resolutions": { + "jquery": "~1.12.4" + }, "overrides": { "jquery-ui": { "main": [ diff --git a/database/3.0_to_attributes.sql b/database/3.0_to_attributes.sql new file mode 100644 index 000000000..1af1970ff --- /dev/null +++ b/database/3.0_to_attributes.sql @@ -0,0 +1,191 @@ + +CREATE TABLE IF NOT EXISTS `ospos_attribute_definitions` ( + `definition_id` INT(10) NOT NULL AUTO_INCREMENT, + `definition_name` VARCHAR(255) NOT NULL, + `definition_type` VARCHAR(45) NOT NULL, + `definition_flags` TINYINT(4) NOT NULL, + `definition_fk` INT(10) NULL, + `deleted` TINYINT(1) NOT NULL DEFAULT 0, + PRIMARY KEY (`definition_id`), + KEY `definition_fk` (`definition_fk`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +CREATE TABLE IF NOT EXISTS `ospos_attribute_values` ( + `attribute_id` INT NOT NULL AUTO_INCREMENT, + `attribute_value` VARCHAR(45) NULL, + PRIMARY KEY (`attribute_id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8; + + +CREATE TABLE IF NOT EXISTS `ospos_attribute_links` ( + `attribute_id` INT NULL, + `definition_id` INT NOT NULL, + `item_id` INT NULL, + `sale_id` INT NULL, + `receiving_id` INT NULL, + KEY `attribute_id` (`attribute_id`), + KEY `definition_id` (`definition_id`), + KEY `item_id` (`item_id`), + KEY `sale_id` (`sale_id`), + KEY `receiving_id` (`receiving_id`), + UNIQUE `attribute_links_uq1` (`attribute_id`, `definition_id`, `item_id`, `sale_id`, `receiving_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +ALTER TABLE `ospos_attribute_definitions` + ADD CONSTRAINT `fk_ospos_attribute_definitions_ibfk_1` FOREIGN KEY (`definition_fk`) REFERENCES `ospos_attribute_definitions` (`definition_id`); + + +ALTER TABLE `ospos_attribute_links` + ADD CONSTRAINT `ospos_attribute_links_ibfk_1` FOREIGN KEY (`definition_id`) REFERENCES `ospos_attribute_definitions` (`definition_id`) ON DELETE CASCADE, + ADD CONSTRAINT `ospos_attribute_links_ibfk_2` FOREIGN KEY (`attribute_id`) REFERENCES `ospos_attribute_values` (`attribute_id`) ON DELETE CASCADE, + ADD CONSTRAINT `ospos_attribute_links_ibfk_3` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`), + ADD CONSTRAINT `ospos_attribute_links_ibfk_4` FOREIGN KEY (`receiving_id`) REFERENCES `ospos_receivings` (`receiving_id`), + ADD CONSTRAINT `ospos_attribute_links_ibfk_5` FOREIGN KEY (`sale_id`) REFERENCES `ospos_sales` (`sale_id`); + + +UPDATE `ospos_modules` SET `sort` = 120 WHERE `name_lang_key` = 'module_config'; + +INSERT INTO `ospos_modules` (`name_lang_key`, `desc_lang_key`, `sort`, `module_id`) VALUES + ('module_attributes', 'module_attributes_desc', 110, 'attributes'); + +INSERT INTO `ospos_permissions` (`permission_id`, `module_id`) VALUES + ('attributes', 'attributes'); + +INSERT INTO `ospos_grants` (`permission_id`, `person_id`) VALUES + ('attributes', 1); + +-- migrate categories to attribute table +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT category, 'CATEGORY' from ospos_items; +INSERT INTO `ospos_attribute_links` (item_id, definition_id) + SELECT item_id, definition_id FROM ospos_items + JOIN ospos_attribute_definitions ON ospos_attribute_definitions.definition_name = ospos_items.category; + +-- migrate custom fields to text attributes +-- NOTE: items with custom attributes won't keep their selected category!! +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config where `key` = 'custom1'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config where `key` = 'custom2'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config where `key` = 'custom3'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config where `key` = 'custom4'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config where `key` = 'custom5'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config where `key` = 'custom6'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config where `key` = 'custom7'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config where `key` = 'custom8'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config where `key` = 'custom9'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config where `key` = 'custom10'; + +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom1_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom1 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom2_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom2 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom3_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom3 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom4_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom4 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom5_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom5 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom6_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom6 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom7_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom7 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom8_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom8 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom9_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom9 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom10_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom10 IS NOT NULL; + +INSERT INTO ospos_attribute_values (attribute_value) SELECT custom1 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT custom2 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT custom3 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT custom4 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT custom5 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT custom6 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT custom7 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT custom8 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT custom9 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT custom10 FROM ospos_items; + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom1 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom1_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom2 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom2_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom3 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom3_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom4 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom4_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom5 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom5_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom6 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom6_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom7 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom7_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom8 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom8_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom9 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom9_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom10 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom10_name')); + +ALTER TABLE `ospos_items` + DROP COLUMN `custom1`, + DROP COLUMN `custom2`, + DROP COLUMN `custom3`, + DROP COLUMN `custom4`, + DROP COLUMN `custom5`, + DROP COLUMN `custom6`, + DROP COLUMN `custom7`, + DROP COLUMN `custom8`, + DROP COLUMN `custom9`, + DROP COLUMN `custom10`, + DROP COLUMN `category`; \ No newline at end of file diff --git a/database/3.1.0_to_attributes.sql b/database/3.1.0_to_attributes.sql new file mode 100644 index 000000000..95e4dfbdb --- /dev/null +++ b/database/3.1.0_to_attributes.sql @@ -0,0 +1,191 @@ + +CREATE TABLE IF NOT EXISTS `ospos_attribute_definitions` ( + `definition_id` INT(10) NOT NULL AUTO_INCREMENT, + `definition_name` VARCHAR(255) NOT NULL, + `definition_type` VARCHAR(45) NOT NULL, + `definition_flags` TINYINT(4) NOT NULL, + `definition_fk` INT(10) NULL, + `deleted` TINYINT(1) NOT NULL DEFAULT 0, + PRIMARY KEY (`definition_id`), + KEY `definition_fk` (`definition_fk`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +CREATE TABLE IF NOT EXISTS `ospos_attribute_values` ( + `attribute_id` INT NOT NULL AUTO_INCREMENT, + `attribute_value` VARCHAR(45) NULL, + PRIMARY KEY (`attribute_id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8; + + +CREATE TABLE IF NOT EXISTS `ospos_attribute_links` ( + `attribute_id` INT NULL, + `definition_id` INT NOT NULL, + `item_id` INT NULL, + `sale_id` INT NULL, + `receiving_id` INT NULL, + KEY `attribute_id` (`attribute_id`), + KEY `definition_id` (`definition_id`), + KEY `item_id` (`item_id`), + KEY `sale_id` (`sale_id`), + KEY `receiving_id` (`receiving_id`), + UNIQUE `attribute_links_uq1` (`attribute_id`, `definition_id`, `item_id`, `sale_id`, `receiving_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +ALTER TABLE `ospos_attribute_definitions` + ADD CONSTRAINT `fk_ospos_attribute_definitions_ibfk_1` FOREIGN KEY (`definition_fk`) REFERENCES `ospos_attribute_definitions` (`definition_id`); + + +ALTER TABLE `ospos_attribute_links` + ADD CONSTRAINT `ospos_attribute_links_ibfk_1` FOREIGN KEY (`definition_id`) REFERENCES `ospos_attribute_definitions` (`definition_id`) ON DELETE CASCADE, + ADD CONSTRAINT `ospos_attribute_links_ibfk_2` FOREIGN KEY (`attribute_id`) REFERENCES `ospos_attribute_values` (`attribute_id`) ON DELETE CASCADE, + ADD CONSTRAINT `ospos_attribute_links_ibfk_3` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`), + ADD CONSTRAINT `ospos_attribute_links_ibfk_4` FOREIGN KEY (`receiving_id`) REFERENCES `ospos_receivings` (`receiving_id`), + ADD CONSTRAINT `ospos_attribute_links_ibfk_5` FOREIGN KEY (`sale_id`) REFERENCES `ospos_sales` (`sale_id`); + + +UPDATE `ospos_modules` SET `sort` = 120 WHERE `name_lang_key` = 'module_config'; + +INSERT INTO `ospos_modules` (`name_lang_key`, `desc_lang_key`, `sort`, `module_id`) VALUES + ('module_attributes', 'module_attributes_desc', 110, 'attributes'); + +INSERT INTO `ospos_permissions` (`permission_id`, `module_id`) VALUES + ('attributes', 'attributes'); + +INSERT INTO `ospos_grants` (`permission_id`, `person_id`) VALUES + ('attributes', 1); + +-- migrate categories to attribute table +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT DISTINCT category, 'CATEGORY' from ospos_items; +INSERT INTO `ospos_attribute_links` (item_id, definition_id) + SELECT item_id, definition_id FROM ospos_items + JOIN ospos_attribute_definitions ON ospos_attribute_definitions.definition_name = ospos_items.category; + +-- migrate custom fields to text attributes +-- NOTE: items with custom attributes won't keep their selected category!! +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom1_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom2_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom3_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom4_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom5_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom6_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom7_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom8_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom9_name'; +INSERT INTO `ospos_attribute_definitions` (definition_name, definition_type) SELECT `value`, 'TEXT' FROM ospos_app_config WHERE `key` = 'custom10_name'; + +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom1_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom1 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom2_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom2 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom3_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom3 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom4_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom4 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom5_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom5 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom6_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom6 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom7_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom7 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom8_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom8 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom9_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom9 IS NOT NULL; +INSERT INTO ospos_attribute_links (definition_id, item_id) SELECT definition_id, item_id FROM ospos_attribute_definitions, ospos_app_config, ospos_items + WHERE ospos_app_config.`key` = 'custom10_name' AND ospos_app_config.`value` = ospos_attribute_definitions.definition_name AND custom10 IS NOT NULL; + +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom1 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom2 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom3 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom4 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom5 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom6 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom7 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom8 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom9 FROM ospos_items; +INSERT INTO ospos_attribute_values (attribute_value) SELECT DISTINCT custom10 FROM ospos_items; + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom1 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom1_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom2 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom2_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom3 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom3_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom4 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom4_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom5 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom5_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom6 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom6_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom7 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom7_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom8 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom8_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom9 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom9_name')); + +UPDATE ospos_attribute_links + INNER JOIN ospos_items ON ospos_attribute_links.item_id = ospos_items.item_id + INNER JOIN ospos_attribute_values ON attribute_value = custom10 + SET ospos_attribute_links.attribute_id = ospos_attribute_values.attribute_id + WHERE definition_id IN (SELECT definition_id FROM ospos_attribute_definitions + WHERE definition_name = (SELECT `value` FROM ospos_app_config WHERE `key` = 'custom10_name')); + +ALTER TABLE `ospos_items` + DROP COLUMN `custom1`, + DROP COLUMN `custom2`, + DROP COLUMN `custom3`, + DROP COLUMN `custom4`, + DROP COLUMN `custom5`, + DROP COLUMN `custom6`, + DROP COLUMN `custom7`, + DROP COLUMN `custom8`, + DROP COLUMN `custom9`, + DROP COLUMN `custom10`, + DROP COLUMN `category`; diff --git a/database/constraints.sql b/database/constraints.sql index a293fc690..65d7f51fe 100644 --- a/database/constraints.sql +++ b/database/constraints.sql @@ -118,6 +118,22 @@ ALTER TABLE `ospos_suppliers` ALTER TABLE `ospos_giftcards` ADD CONSTRAINT `ospos_giftcards_ibfk_1` FOREIGN KEY (`person_id`) REFERENCES `ospos_people` (`person_id`); +-- +-- Constraints for table `ospos_attribute_definitions` +-- +ALTER TABLE `ospos_attribute_definitions` + ADD CONSTRAINT `fk_ospos_attribute_definitions_ibfk_1` FOREIGN KEY (`definition_fk`) REFERENCES `ospos_attribute_definitions` (`definition_id`); + +-- +-- Constraints for table `ospos_attribute_links` +-- +ALTER TABLE `ospos_attribute_links` + ADD CONSTRAINT `ospos_attribute_links_ibfk_1` FOREIGN KEY (`definition_id`) REFERENCES `ospos_attribute_definitions` (`definition_id`) ON DELETE CASCADE, + ADD CONSTRAINT `ospos_attribute_links_ibfk_2` FOREIGN KEY (`attribute_id`) REFERENCES `ospos_attribute_values` (`attribute_id`) ON DELETE CASCADE, + ADD CONSTRAINT `ospos_attribute_links_ibfk_3` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`), + ADD CONSTRAINT `ospos_attribute_links_ibfk_4` FOREIGN KEY (`receiving_id`) REFERENCES `ospos_receivings` (`receiving_id`) ON DELETE CASCADE, + ADD CONSTRAINT `ospos_attribute_links_ibfk_5` FOREIGN KEY (`sale_id`) REFERENCES `ospos_sales` (`sale_id`) ON DELETE CASCADE; + -- -- Constraints for table `ospos_customers_points` -- @@ -130,4 +146,4 @@ ALTER TABLE `ospos_customers_points` -- Constraints for table `ospos_sales_reward_points` -- ALTER TABLE `ospos_sales_reward_points` - ADD CONSTRAINT `ospos_sales_reward_points_ibfk_1` FOREIGN KEY (`sale_id`) REFERENCES `ospos_sales` (`sale_id`); + ADD CONSTRAINT `ospos_sales_reward_points_ibfk_1` FOREIGN KEY (`sale_id`) REFERENCES `ospos_sales_items` (`sale_id`); diff --git a/database/tables.sql b/database/tables.sql index 6a63bfbbc..32d304fb0 100644 --- a/database/tables.sql +++ b/database/tables.sql @@ -229,7 +229,6 @@ CREATE TABLE `ospos_inventory` ( CREATE TABLE `ospos_items` ( `name` varchar(255) NOT NULL, - `category` varchar(255) NOT NULL, `supplier_id` int(11) DEFAULT NULL, `item_number` varchar(255) DEFAULT NULL, `description` varchar(255) NOT NULL, @@ -248,16 +247,6 @@ CREATE TABLE `ospos_items` ( `pack_name` varchar(8) DEFAULT '', `low_sell_item_id` int(10) DEFAULT 0, `deleted` int(1) NOT NULL DEFAULT '0', - `custom1` VARCHAR(255) DEFAULT NULL, - `custom2` VARCHAR(255) DEFAULT NULL, - `custom3` VARCHAR(255) DEFAULT NULL, - `custom4` VARCHAR(255) DEFAULT NULL, - `custom5` VARCHAR(255) DEFAULT NULL, - `custom6` VARCHAR(255) DEFAULT NULL, - `custom7` VARCHAR(255) DEFAULT NULL, - `custom8` VARCHAR(255) DEFAULT NULL, - `custom9` VARCHAR(255) DEFAULT NULL, - `custom10` VARCHAR(255) DEFAULT NULL, PRIMARY KEY (`item_id`), KEY `item_number` (`item_number`), KEY `supplier_id` (`supplier_id`) @@ -363,7 +352,7 @@ CREATE TABLE `ospos_modules` ( -- INSERT INTO `ospos_modules` (`name_lang_key`, `desc_lang_key`, `sort`, `module_id`) VALUES -('module_config', 'module_config_desc', 110, 'config'), +('module_config', 'module_config_desc', 120, 'config'), ('module_customers', 'module_customers_desc', 10, 'customers'), ('module_employees', 'module_employees_desc', 80, 'employees'), ('module_giftcards', 'module_giftcards_desc', 90, 'giftcards'), @@ -376,7 +365,8 @@ INSERT INTO `ospos_modules` (`name_lang_key`, `desc_lang_key`, `sort`, `module_i ('module_reports', 'module_reports_desc', 50, 'reports'), ('module_sales', 'module_sales_desc', 70, 'sales'), ('module_suppliers', 'module_suppliers_desc', 40, 'suppliers'), -('module_taxes', 'module_taxes_desc', 105, 'taxes'); +('module_taxes', 'module_taxes_desc', 105, 'taxes'), +('module_attributes', 'module_attributes_desc', 110, 'attributes'); -- -------------------------------------------------------- @@ -452,7 +442,8 @@ INSERT INTO `ospos_permissions` (`permission_id`, `module_id`) VALUES ('sales', 'sales'), ('config', 'config'), ('suppliers', 'suppliers'), -('taxes', 'taxes'); +('taxes', 'taxes'), +('attributes', 'attributes'); @@ -507,6 +498,7 @@ INSERT INTO `ospos_grants` (`permission_id`, `person_id`, `menu_group`) VALUES ('suppliers', 1, 'home'), ('taxes', 1, 'office'), ('office', 1, 'home'), +('attributes', 1, 'office'), ('home', 1, 'office'); -- @@ -809,6 +801,68 @@ CREATE TABLE IF NOT EXISTS `ospos_tax_code_rates` ( -- +-- -------------------------------------------------------- + +-- +-- Table structure for table `ospos_attribute_definitions` +-- + +CREATE TABLE IF NOT EXISTS `ospos_attribute_definitions` ( + `definition_id` INT(10) NOT NULL AUTO_INCREMENT, + `definition_name` VARCHAR(255) NOT NULL, + `definition_type` VARCHAR(45) NOT NULL, + `definition_flags` TINYINT(4) NOT NULL, + `definition_fk` INT(10) NULL, + `deleted` TINYINT(1) NOT NULL DEFAULT 0, + PRIMARY KEY (`definition_id`), + KEY `definition_fk` (`definition_fk`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; + +-- +-- Dumping data for table `ospos_attribute_definitions` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `ospos_attribute_values` +-- + +CREATE TABLE IF NOT EXISTS `ospos_attribute_values` ( + `attribute_id` INT NOT NULL AUTO_INCREMENT, + `attribute_value` VARCHAR(45) NULL, + PRIMARY KEY (`attribute_id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; + + +-- +-- Dumping data for table `ospos_attribute_values` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `ospos_attribute_links` +-- + +CREATE TABLE IF NOT EXISTS `ospos_attribute_links` ( + `attribute_id` INT NULL, + `definition_id` INT NOT NULL, + `item_id` INT NULL, + `sale_id` INT NULL, + `receiving_id` INT NULL, + KEY `attribute_id` (`attribute_id`), + KEY `definition_id` (`definition_id`), + KEY `item_id` (`item_id`), + KEY `sale_id` (`sale_id`), + KEY `receiving_id` (`receiving_id`), + UNIQUE `attribute_links_uq1` (`attribute_id`, `definition_id`, `item_id`, `sale_id`, `receiving_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; + +-- +-- Dumping data for table `ospos_attribute_links` +-- + -- -------------------------------------------------------- -- diff --git a/design/ospos_categories.mwb b/design/ospos_categories.mwb index d13a13b71..755f93431 100644 Binary files a/design/ospos_categories.mwb and b/design/ospos_categories.mwb differ diff --git a/design/ospos_categories.mwb.bak b/design/ospos_categories.mwb.bak new file mode 100644 index 000000000..50d274a08 Binary files /dev/null and b/design/ospos_categories.mwb.bak differ diff --git a/import_items.csv b/import_items.csv index 01de41cd9..8e083f017 100644 --- a/import_items.csv +++ b/import_items.csv @@ -1,2 +1,2 @@ -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,custom1,custom2,custom3,custom4,custom5,custom6,custom7,custom8,custom9,custom10,item_image,location1,quantity1 -33333333,Apple iMac,Computers,,800,1200,Tax 1,8,Tax 2,10,1,Best Computer ever,y,,"Oz, Frank",The Bunny and the Hill,"Monkeys,Giraffes,Gorillas",English,New,Apple,,1999,D3lk3jlkjs,Hardbound,item.jpg,1,100 +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,location_id,quantity,pic_idN +33333334,Apple iMac,Computers,,800,1200,Tax 1,8,Tax 2,10,1,Best Computer ever,y,,1,100,null diff --git a/license/.licenses b/license/.licenses new file mode 100644 index 000000000..3fc01c60a --- /dev/null +++ b/license/.licenses @@ -0,0 +1,28 @@ + + +=== [ NON-BOWER ] === +blockUI +bootstrap +bootstrap-daterangepicker +bootstrap-select +bootstrap-table +bootstrap3-dialog +bootswatch +chartist +chartist-plugin-axistitle +chartist-plugin-pointlabels +chartist-plugin-tooltip +file-saver.js +html2canvas +jasny-bootstrap +jquery +jquery-form +jquery-ui +jquery-validate +js-cookie +jspdf +jspdf-autotable +moment +remarkable-bootstrap-notify +smalot-bootstrap-datetimepicker +tableExport.jquery.plugin \ No newline at end of file diff --git a/public/images/menubar/attributes.png b/public/images/menubar/attributes.png new file mode 100644 index 000000000..5c39d2ea7 Binary files /dev/null and b/public/images/menubar/attributes.png differ