setTable('price_overrides'); price_overrides_schema_bootstrap::ensureColumns(); } public function objectChanged(): void { // No need to invalidate the cache, since the user_price_overrides object is not cached } public function getObjectProperties(): void { $this->is_category = new object_property($this->table, $this->id, 'is_category', 'bool', true); $this->product_or_category_id = new object_property($this->table, $this->id, 'product_or_category_id', 'int', true); $this->percentage = new object_property($this->table, $this->id, 'percentage', 'int', true); $this->fixed_price = new object_property($this->table, $this->id, 'fixed_price', 'int', false, null); } public function setUser($user_id): user_price_overrides_o { $this->user_id = $user_id; return $this; } /** * Set a price override for the user * @param bool $is_category * @param int|string $product_or_category_id * @param int $percentage * @param int|null $fixed_price * @return $this */ public function setPrice(bool $is_category, int|string $product_or_category_id, int $percentage, ?int $fixed_price = null): user_price_overrides_o { global $db; // If the user is not set, return the object if (!isset($this->user_id)) { return $this; } if ($is_category) { $fixed_price = null; } // Check if the record already exists $this->removePriceIfExist($is_category, $product_or_category_id); // If neither a discount nor a fixed product price is set, remove the record. if ($percentage === 0 && $fixed_price === null) { return $this; } // Create a new record in the database $product_or_category_id = $db->escape_string((string)$product_or_category_id); $fixed_price_sql = $fixed_price === null ? 'NULL' : (string)max(0, (int)$fixed_price); $sql = "INSERT INTO $this->table (user_id, is_category, product_or_category_id, percentage, fixed_price) VALUES (" . (int)$this->user_id . ", " . (int)$is_category . ", '$product_or_category_id', " . (int)$percentage . ", $fixed_price_sql)"; $db->query($sql); $this->markSearchDirty(); return $this; } private function removePriceIfExist(bool $is_category, int|string $product_or_category_id): void { global $db; $product_or_category_id = $db->escape_string((string)$product_or_category_id); $sql = "DELETE FROM $this->table WHERE user_id = " . (int)$this->user_id . " AND is_category = " . (int)$is_category . " AND product_or_category_id = '$product_or_category_id'"; $db->query($sql); $this->markSearchDirty(); } /** * Get the price override (PERCENTAGE) for the user * @param bool $is_category * @param int|string $product_or_category_id * @return int */ public function getPrice(bool $is_category, int|string $product_or_category_id): int { global /** @var db $db */ $db; $sql = "SELECT * FROM $this->table WHERE user_id = " . $this->user_id . " AND is_category = " . (int)$is_category . " AND product_or_category_id = "; // If the is_category is false, the product_or_category_id is a product_id if (!$is_category) { $product_or_category_id = (int)$product_or_category_id; $sql .= $product_or_category_id; } else { // If the is_category is true, the product_or_category_id is a category_id $product_or_category_id = $db->escape_string($product_or_category_id); $sql .= "'$product_or_category_id'"; } // Get the price override from the database $result = $db->query($sql); $percentage = 0; if ($result->num_rows > 0) { // Return the percentage $percentage = $result->fetch_assoc()['percentage']; } // If the object is a product, check if the category has a discount set if (!$is_category) { $product = (new products_o())->getProductById($product_or_category_id); if ($product->apply_category_discount->value()) { // Get the economic user discount $economic_user_global_discount = (new users_o())->getUserById($this->user_id)->getEconomicCustomerDiscountPercentage(); // Get the category discount $sql = "SELECT * FROM $this->table WHERE user_id = " . $this->user_id . " AND is_category = 1 AND product_or_category_id = '" . $product->category->value() . "'"; $result = $db->query($sql); if ($result->num_rows > 0) { $category_discount = $result->fetch_assoc()['percentage']; // If the category discount is higher than the product discount, return the category discount if ((int)$category_discount > (int)$percentage && (int)$category_discount > (int)$economic_user_global_discount) { return $category_discount; } } // If the economic user discount is higher than the product discount, return the economic user discount if ((int)$economic_user_global_discount > (int)$percentage) { return $economic_user_global_discount; } } } return $percentage; } public function getFixedPrice(bool $is_category, int|string $product_or_category_id): ?int { if ($is_category || !isset($this->user_id)) { return null; } $row = $this->getDirectPriceRow(false, (int)$product_or_category_id); if ($row === null || $row['fixed_price'] === null) { return null; } return (int)$row['fixed_price']; } public function getDirectPriceRow(bool $is_category, int|string $product_or_category_id): ?array { global $db; if (!isset($this->user_id)) { return null; } $product_or_category_id = $db->escape_string((string)$product_or_category_id); $sql = "SELECT * FROM $this->table WHERE user_id = " . (int)$this->user_id . " AND is_category = " . (int)$is_category . " AND product_or_category_id = '$product_or_category_id' LIMIT 1"; $result = $db->query($sql); if (!$result || $result->num_rows < 1) { return null; } $row = $result->fetch_assoc(); $row['id'] = (int)$row['id']; $row['user_id'] = (int)$row['user_id']; $row['is_category'] = (bool)$row['is_category']; $row['product_or_category_id'] = $is_category ? (string)$row['product_or_category_id'] : (int)$row['product_or_category_id']; $row['percentage'] = (int)$row['percentage']; $row['fixed_price'] = array_key_exists('fixed_price', $row) && $row['fixed_price'] !== null ? (int)$row['fixed_price'] : null; return $row; } /** * Get all the price overrides for the user * @return array */ public function getAllPrices(): array { global $db; // Get the customers global discount $economic_user_global_discount = (new users_o())->getUserById($this->user_id)->getEconomicCustomerDiscountPercentage(); // Get all the price overrides for the user $sql = "SELECT * FROM $this->table WHERE user_id = " . $this->user_id; $result = $db->query($sql); $prices = []; if ($result->num_rows > 0) { while ($row = $result->fetch_assoc()) { // Parse the row $row['id'] = (int)$row['id']; $row['user_id'] = (int)$row['user_id']; $row['is_category'] = (bool)$row['is_category']; $row['product_or_category_id'] = (int)$row['product_or_category_id']; $row['percentage'] = (int)$row['percentage']; $row['fixed_price'] = array_key_exists('fixed_price', $row) && $row['fixed_price'] !== null ? (int)$row['fixed_price'] : null; $row['created_at'] = (string)$row['created_at']; $row['updated_at'] = (string)$row['updated_at']; // Add the row to the list $prices[] = $row; } } // If the user has a global discount, add it to the list if ($economic_user_global_discount > 0) { $prices[] = [ 'id' => (int)999999, 'user_id' => (int)$this->user_id, 'is_category' => true, 'product_or_category_id' => "global", 'percentage' => (int)$economic_user_global_discount, 'fixed_price' => null, 'created_at' => "2021-01-01 00:00:00", 'updated_at' => "2021-01-01 00:00:00" ]; } return $prices; } private function markSearchDirty(): void { try { system_search_cache::markDirtyTable($this->table); } catch (\Throwable) { } } }