/**
  * Update the database values for an existing contract price item.
  * 
  * @param $price_item the contract price item to be updated
  * @return result receipt from the db operation
  */
 function update_contract_price_item(rental_contract_price_item $price_item)
 {
     $id = intval($price_item->get_id());
     $one_time = $price_item->get_is_one_time();
     $values = array('price_item_id = ' . $price_item->get_price_item_id(), 'contract_id = ' . $price_item->get_contract_id(), 'area = ' . str_replace(',', '.', $price_item->get_area()), 'count = ' . str_replace(',', '.', $price_item->get_count()), 'title = \'' . $price_item->get_title() . '\'', 'agresso_id = \'' . $price_item->get_agresso_id() . '\'', 'is_area = ' . ($price_item->is_area() ? "true" : "false"), 'is_one_time = ' . (isset($one_time) && ($price_item->is_one_time() || $price_item->get_is_one_time() == 1) ? "true" : "false"), 'price = ' . str_replace(',', '.', $price_item->get_price()));
     if ($price_item->is_area()) {
         //			var_dump('total_price = '.$price_item->get_area().'*'.$price_item->get_price());
         $values[] = 'total_price = ' . str_replace(',', '.', $price_item->get_area() * $price_item->get_price());
     } else {
         //			var_dump('total_price = '.$price_item->get_count().'*'.$price_item->get_price());
         $values[] = 'total_price = ' . str_replace(',', '.', $price_item->get_count() * $price_item->get_price());
     }
     if ($price_item->get_date_start()) {
         $values[] = 'date_start = ' . $this->marshal($price_item->get_date_start(), 'int');
     }
     if ($price_item->get_date_end()) {
         $values[] = 'date_end = ' . $this->marshal($price_item->get_date_end(), 'int');
     }
     $this->db->query('UPDATE rental_contract_price_item SET ' . join(',', $values) . " WHERE id={$id}", __LINE__, __FILE__);
     $receipt['id'] = $id;
     $receipt['message'][] = array('msg' => lang('Entity %1 has been updated', $entry['id']));
     return $receipt;
 }
 protected function import_contract_price_items($contracts)
 {
     $start_time = time();
     $soprice_item = rental_soprice_item::get_instance();
     $socontract_price_item = rental_socontract_price_item::get_instance();
     $socontract = rental_socontract::get_instance();
     // Read priselementdetaljkontrakt list first so we can create our complete price items in the next loop
     // This is an array keyed by the main price item ID
     $detail_price_items = array();
     $datalines = $this->getcsvdata($this->path . "/u_PrisElementDetaljKontrakt.csv");
     $this->messages[] = "Read 'u_PrisElementDetaljKontrakt.csv' file in " . (time() - $start_time) . " seconds";
     $this->messages[] = "'u_PrisElementDetaljKontrakt.csv' contained " . count($datalines) . " lines";
     foreach ($datalines as $data) {
         //Felt fra 'PrisElementDetaljKontrakt'
         if (count($data) <= 10) {
             continue;
         }
         if (isset($detail_price_items[$data[1]])) {
             // Update existing detail only start date is later than existing start date detail
             if (!$this->is_null($data[4])) {
                 $detail_date = strtotime($this->decode($data[4]));
                 if ($detail_date > $detail_price_items[$data[1]]['date_start']) {
                     $detail_price_items[$data[1]]['date_start'] = $detail_date;
                     $detail_price_items[$data[1]]['amount'] = str_replace(',', '.', $data[3]);
                     $detail_price_items[$data[1]]['price'] = str_replace(',', '.', $data[2]);
                 }
             }
         } else {
             //Create a row in the array holding the details (price, amount, dates) for the price item
             $detail_price_items[$data[1]] = array('price' => str_replace(',', '.', $data[2]), 'amount' => str_replace(',', '.', $data[3]), 'date_start' => null, 'date_end' => null);
             if (!$this->is_null($data[4])) {
                 $detail_price_items[$data[1]]['date_start'] = strtotime($this->decode($data[4]));
             }
             if (!$this->is_null($data[5])) {
                 $detail_price_items[$data[1]]['date_end'] = strtotime($this->decode($data[5]));
             }
         }
     }
     $datalines = $this->getcsvdata($this->path . "/u_PrisElementKontrakt.csv");
     $this->messages[] = "Read 'u_PrisElementKontrakt.csv' file in " . (time() - $start_time) . " seconds";
     $this->messages[] = "'u_PrisElementKontrakt.csv' contained " . count($datalines) . " lines";
     //Retrieve the title for the responsibility area we are importing (to hande the respoonsibility areas differently)
     $title = $socontract->get_responsibility_title($this->location_id);
     //If we are importing price items for 'Innleie', we have a default price item in the 'Prisbok' with agresso-id 'INNLEIE'
     if ($title == 'contract_type_innleie') {
         $admin_price_item = $soprice_item->get_single_with_id('INNLEIE');
     }
     foreach ($datalines as $data) {
         if (count($data) <= 24) {
             continue;
         }
         /* If we are importing contract price items for external or internal:
          * - see if a pricebook element exist
          */
         if ($title != 'contract_type_innleie') {
             // The Agresso-ID is unique for price items
             $id = $this->decode($data[12]);
             //cVarenr
             $admin_price_item = null;
             if (isset($id) && $id != '') {
                 $admin_price_item = $soprice_item->get_single_with_id($id);
             } else {
                 $admin_price_item = $soprice_item->get_single_with_id('UNKNOWN');
             }
         }
         // Get the facilit price item id so that we can retrieve the price item details
         $facilit_id = $this->decode($data[0]);
         //nPrisElementId
         /* Create a new pricebook price item if one does not exist in the pricebook; store it if it has a new unique agresso-id. 
          * Note: First price item with unique agresso-id determines title, area or "nr of items", and the price (from the price item details) */
         if ($admin_price_item == null) {
             $admin_price_item = new rental_price_item();
             $admin_price_item->set_title($this->decode($data[3]));
             //cPrisElementNavn
             $admin_price_item->set_agresso_id($id);
             //cVareNr
             // This assumes 1 for AREA, and anything else for count, even blanks
             $admin_price_item->set_is_area($this->decode($data[4]) == '1' ? true : false);
             //nMengdeTypeId
             // This assumes -1 for adjustable, and anything else for not adjustable, even blanks
             $admin_price_item->set_is_adjustable($this->decode($data[17]) == '-1' ? true : false);
             //bRegulerbar
             // Get the price for this price item
             $admin_price_item->set_price($detail_price_items[$facilit_id]['price']);
             $admin_price_item->set_responsibility_id($this->location_id);
             if (isset($id)) {
                 $soprice_item->store($admin_price_item);
                 $this->messages[] = "Stored price item ({$id}) with title " . $admin_price_item->get_title() . " in 'Prisbok'";
             }
         } else {
             //check type on price item (not is_area and data[4]=1, or is_area and data[4] != 1)
             if ($admin_price_item->is_area() && $this->decode($data[4] != '1')) {
                 $this->warnings[] = "Price item ({$admin_price_item->get_agresso_id()}) - " . $admin_price_item->get_title() . " - on contract {$contracts[$this->decode($data[1])]} is stored as area price item, but has record indicating it is not an area price item!";
             } else {
                 if (!$admin_price_item->is_area() && $this->decode($data[4] == '1')) {
                     $this->warnings[] = "Price item ({$admin_price_item->get_agresso_id()}) - " . $admin_price_item->get_title() . " - on contract {$contracts[$this->decode($data[1])]} is stored as non-area price item, but has record indicating it is an area price item!";
                 }
             }
         }
         $contract_id = $contracts[$this->decode($data[1])];
         //nKontraktId
         if ($contract_id) {
             // Create a new contract price item that we can tie to our contract
             $price_item = new rental_contract_price_item();
             // Retrieve the contract
             $contract = $socontract->get_single($contract_id);
             // Set cLonnsArt for price item as contract reference
             $contract->set_reference($this->decode($data[13]));
             // The contract price item title should be the same as in the price book for internal
             if ($title == 'contract_type_internleie') {
                 $price_item->set_title($admin_price_item->get_title());
             } else {
                 // ... and overridden by the price item for innleie and external
                 $price_item->set_title($data[3]);
             }
             // Set the price book element's agresso-id and type (area/piece)
             $price_item->set_agresso_id($admin_price_item->get_agresso_id());
             // If the price item is unknown do not use the 'is_area' from the price book
             if ($admin_price_item->get_agresso_id() != 'UNKNOWN') {
                 $price_item->set_is_area($admin_price_item->is_area());
             } else {
                 $price_item->set_is_area($this->decode($data[4]) == '1' ? true : false);
             }
             // Get the price for the price item details
             $price_item->set_price($detail_price_items[$facilit_id]['price']);
             // Give a warning if a contract has a price element of type area with are like 1
             if ($price_item->is_area() && $detail_price_items[$facilit_id]['amount'] == '1') {
                 $this->warnings[] = "Contract " . $contract->get_old_contract_id() . " has a price item of type area with amount like 1";
             }
             // Tie this price item to its parent admin price item
             $price_item->set_price_item_id($admin_price_item->get_id());
             if ($admin_price_item->is_area()) {
                 $rented_area = $contract->get_rented_area();
                 if (isset($rented_area)) {
                     if ($detail_price_items[$facilit_id]['amount'] != $rented_area) {
                         if ($rented_area == 0) {
                             $contract->set_rented_area($detail_price_items[$facilit_id]['amount']);
                             $this->warnings[] = "Price item {$id} - (Facilit ID {$facilit_id}) has area " . $detail_price_items[$facilit_id]['amount'] . " while contract {$contract_id} already has rented area set to 0. Using rented area from price item.";
                         } else {
                             $this->warnings[] = "Price item {$id} - (Facilit ID {$facilit_id}) has area " . $detail_price_items[$facilit_id]['amount'] . " while contract {$contract_id} already has rented area {$rented_area}. Using rented area on contract.";
                         }
                     }
                 } else {
                     //Store price item area on contract if the contract has no area (not from contract)
                     $contract->set_rented_area($detail_price_items[$facilit_id]['amount']);
                     $this->message[] = "Price item {$id} - (Facilit ID {$facilit_id}) has area " . $detail_price_items[$facilit_id]['amount'] . " while contract {$contract_id} already no area {$rented_area}. Using rented area on price item.";
                     //Store the contract
                     $socontract->store($contract);
                 }
                 // Set the the contract area on the price item
                 $price_item->set_area($contract->get_rented_area());
                 //Calculate the total price for the price item
                 $item_area = $price_item->get_area();
                 $item_price = $price_item->get_price();
                 $price_item->set_total_price($item_area * $item_price);
             } else {
                 $price_item->set_count($detail_price_items[$facilit_id]['amount']);
                 $item_count = $price_item->get_count();
                 $item_price = $price_item->get_price();
                 $price_item->set_total_price($item_count * $item_price);
             }
             $price_item->set_date_start($detail_price_items[$facilit_id]['date_start']);
             $price_item->set_date_end($detail_price_items[$facilit_id]['date_end']);
             // Tie the price item to the contract it belongs to
             $price_item->set_contract_id($contract_id);
             // Tie this price item to its parent admin price item
             $price_item->set_price_item_id($admin_price_item->get_id());
             //update contract with adjustment share
             $adjustment_share = $this->decode($data[18]);
             //nReguleringsandel
             if ($adjustment_share != null && $adjustment_share > 0) {
                 $socontract->update_adjustment_share($contract_id, $adjustment_share);
             }
             // .. and save
             if ($socontract_price_item->import($price_item)) {
                 $this->messages[] = "Successfully imported price item ({$id}) for contract {$contract_id}";
             } else {
                 $this->warnings[] = "Could not store price item ({$id}) - " . $price_item->get_title();
             }
         } else {
             $this->warnings[] = "Skipped price item with no contract attached: " . join(", ", $data);
         }
     }
     $this->messages[] = "Imported contract price items. (" . (time() - $start_time) . " seconds)";
     return true;
 }
 protected function populate(int $price_item_id, &$price_item)
 {
     if ($price_item == null) {
         $price_item = new rental_contract_price_item($this->unmarshal($this->db->f('id'), 'int'));
         $price_item->set_price_item_id($this->unmarshal($this->db->f('price_item_id'), 'int'));
         $price_item->set_contract_id($this->unmarshal($this->db->f('contract_id'), 'int'));
         $price_item->set_title($this->unmarshal($this->db->f('title'), 'string'));
         $price_item->set_agresso_id($this->unmarshal($this->db->f('agresso_id'), 'string'));
         $price_item->set_is_area($this->unmarshal($this->db->f('is_area'), 'bool'));
         $price_item->set_is_one_time($this->unmarshal($this->db->f('is_one_time'), 'bool'));
         $price_item->set_is_billed($this->unmarshal($this->db->f('is_billed'), 'bool'));
         $price_item->set_price($this->unmarshal($this->db->f('price'), 'float'));
         $price_item->set_area($this->unmarshal($this->db->f('area'), 'float'));
         $price_item->set_count($this->unmarshal($this->db->f('count'), 'int'));
         $price_item->set_total_price($this->unmarshal($this->db->f('total_price'), 'float'));
         $price_item->set_date_start($this->unmarshal($this->db->f('date_start'), 'int'));
         $price_item->set_date_end($this->unmarshal($this->db->f('date_end'), 'int'));
         $price_type_id = (int) $this->db->f('type');
         $price_item->set_price_type_id($price_type_id);
         $price_item->set_price_type_title($price_type_id);
     }
     return $price_item;
 }