|
Server : Apache/2.4.18 (Ubuntu) System : Linux canvaswebdesign 3.13.0-71-generic #114-Ubuntu SMP Tue Dec 1 02:34:22 UTC 2015 x86_64 User : oppastar ( 1041) PHP Version : 7.0.33-0ubuntu0.16.04.15 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, Directory : /var/www/laciasmara.com/public_html/shop/application/controllers/ |
Upload File : |
<?php if (!defined('BASEPATH')) {
exit('No direct script access allowed');
}
class Api extends Public_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('category_m');
$this->load->model('Statistic_m');
$this->load->model('Carousel_banner_m');
$this->load->model('Top_banner_m');
$this->load->model('Brand_m');
$this->load->model('stocks_m');
}
public function test()
{
$this->output
->set_content_type('application/json')
->set_output(json_encode([
'status' => 'success',
'message' => 'Controller accessible',
'method' => $_SERVER['REQUEST_METHOD'],
'timestamp' => date('Y-m-d H:i:s')
]));
}
public function popular_categories()
{
$categories = $this->category_m->get_footer_popular_categories();
echo json_encode($categories);
}
public function trending_searches()
{
$trending_searches = $this->Statistic_m->get_trending_searches();
echo json_encode($trending_searches);
}
public function best_seller_products()
{
$this->db->select('
p.id_products,
p.title,
p.alias,
p.brand_id,
p.created_at,
pd.id AS id_detail,
pd.price,
pd.discounted_price,
pd.sku,
COALESCE(GROUP_CONCAT(DISTINCT CONCAT_WS(": ", pa.product_attribute, pad.attribute_detail) SEPARATOR "; "), "No variants available") AS variants,
pi.image AS image,
pi_secondary.image AS image_secondary,
pc.attribute_detail_id,
s.stock,
s.stock_keep,
(s.stock - s.stock_keep) AS stock_sell,
SUM(od.quantity) AS total_sales,
COUNT(pr.id) AS total_reviews,
CASE
WHEN pd.discounted_price IS NOT NULL AND pd.discounted_price > 0 AND pd.discounted_price < pd.price
THEN (pd.price - pd.discounted_price)
ELSE 0
END AS savings_amount,
CASE
WHEN pd.discounted_price IS NOT NULL AND pd.discounted_price > 0 AND pd.discounted_price < pd.price
THEN ROUND(((pd.price - pd.discounted_price) / pd.price) * 100, 0)
ELSE 0
END AS discount_percentage,
-- Badges Information (Added)
COALESCE(product_badges_data.badges_names, "") AS badges_names,
COALESCE(product_badges_data.badges_data, "") AS badges_data,
COALESCE(product_badges_data.badges_count, 0) AS badges_count
')
->from('products p')
->join('product_details pd', 'p.id_products = pd.product_id', 'left')
->join('product_images pi', 'pd.id = pi.product_details_id AND pi.priority = 1 AND pi.status = 1', 'left')
->join('product_images pi_secondary', 'pd.id = pi_secondary.product_details_id AND pi_secondary.priority = 2 AND pi_secondary.status = 1', 'left')
->join('stock s', 'pd.id = s.id_product_detail AND s.warehouse_id = 1', 'left')
->join('orders_detail od', 'od.item_id = pd.id AND od.warehouse_id = 1', 'left')
->join('product_combination pc', 'pd.id = pc.product_details_id', 'left')
->join('product_attributes pa', 'pc.attribute_id = pa.id', 'left')
->join('product_attributes_detail pad', 'pc.attribute_detail_id = pad.id', 'left')
->join('product_review pr', 'pr.product_id = p.id_products', 'left')
// Product Badges Join (Added)
->join('(SELECT
pb.product_id,
COUNT(pb.badge_id) AS badges_count,
GROUP_CONCAT(b.name ORDER BY pb.priority ASC SEPARATOR ", ") AS badges_names,
GROUP_CONCAT(
CONCAT(
b.id, ":",
b.name, ":",
b.slug, ":",
IFNULL(b.description, ""), ":",
IFNULL(b.background_color, "#FF6B6B"), ":",
IFNULL(b.text_color, "#FFFFFF"), ":",
IFNULL(b.icon, ""), ":",
pb.position, ":",
pb.priority
)
ORDER BY pb.priority ASC
SEPARATOR "|"
) AS badges_data
FROM product_badges pb
INNER JOIN badges b ON pb.badge_id = b.id
WHERE pb.is_active = 1
AND b.is_active = 1
AND (pb.start_date IS NULL OR pb.start_date <= NOW())
AND (pb.end_date IS NULL OR pb.end_date >= NOW())
GROUP BY pb.product_id) product_badges_data', 'p.id_products = product_badges_data.product_id', 'left')
->where('p.product_status', '1')
->where('p.deleted_at', null)
->where('s.stock > 1')
->where('(s.stock - s.stock_keep) > 0')
->group_by('p.id_products')
->order_by('total_reviews', 'DESC')
->limit(10);
$top_seller_products = $this->db->get()->result_array();
echo json_encode($top_seller_products);
}
public function new_arrival_products()
{
$this->db->select('
p.id_products,
p.title,
p.alias,
p.brand_id,
p.created_at,
pd.id AS id_detail,
pd.price,
pd.discounted_price,
pd.sku,
COALESCE(GROUP_CONCAT(DISTINCT CONCAT_WS(": ", pa.product_attribute, pad.attribute_detail) SEPARATOR "; "), "No variants available") AS variants,
pi.image AS image,
pi_secondary.image AS image_secondary,
pc.attribute_detail_id,
s.stock,
s.stock_keep,
s.stock_reject,
s.stock_sample,
(s.stock - s.stock_keep - COALESCE(s.stock_reject, 0) - COALESCE(s.stock_sample, 0)) as stock_sell,
SUM(od.quantity) AS total_sales,
COUNT(pr.id) AS total_reviews,
CASE
WHEN pd.discounted_price IS NOT NULL AND pd.discounted_price > 0 AND pd.discounted_price < pd.price
THEN (pd.price - pd.discounted_price)
ELSE 0
END AS savings_amount,
CASE
WHEN pd.discounted_price IS NOT NULL AND pd.discounted_price > 0 AND pd.discounted_price < pd.price
THEN ROUND(((pd.price - pd.discounted_price) / pd.price) * 100, 0)
ELSE 0
END AS discount_percentage,
-- Badges Information (Added)
COALESCE(product_badges_data.badges_names, "") AS badges_names,
COALESCE(product_badges_data.badges_data, "") AS badges_data,
COALESCE(product_badges_data.badges_count, 0) AS badges_count
')
->from('products p')
->join('product_details pd', 'p.id_products = pd.product_id', 'left')
->join('product_images pi', 'pd.id = pi.product_details_id AND pi.priority = 1 AND pi.status = 1', 'left')
->join('product_images pi_secondary', 'pd.id = pi_secondary.product_details_id AND pi_secondary.priority = 2 AND pi_secondary.status = 1', 'left')
->join('stock s', 'pd.id = s.id_product_detail AND s.warehouse_id = 1', 'left')
->join('orders_detail od', 'od.item_id = pd.id AND od.warehouse_id = 1', 'left')
->join('product_combination pc', 'pd.id = pc.product_details_id', 'left')
->join('product_attributes pa', 'pc.attribute_id = pa.id', 'left')
->join('product_attributes_detail pad', 'pc.attribute_detail_id = pad.id', 'left')
->join('product_review pr', 'pr.product_id = p.id_products', 'left')
->join('category_product cp', 'p.id_products = cp.id_product', 'inner')
->join('categories c', 'cp.id_category = c.id_categories', 'inner')
// Product Badges Join (Added)
->join('(SELECT
pb.product_id,
COUNT(pb.badge_id) AS badges_count,
GROUP_CONCAT(b.name ORDER BY pb.priority ASC SEPARATOR ", ") AS badges_names,
GROUP_CONCAT(
CONCAT(
b.id, ":",
b.name, ":",
b.slug, ":",
IFNULL(b.description, ""), ":",
IFNULL(b.background_color, "#FF6B6B"), ":",
IFNULL(b.text_color, "#FFFFFF"), ":",
IFNULL(b.icon, ""), ":",
pb.position, ":",
pb.priority
)
ORDER BY pb.priority ASC
SEPARATOR "|"
) AS badges_data
FROM product_badges pb
INNER JOIN badges b ON pb.badge_id = b.id
WHERE pb.is_active = 1
AND b.is_active = 1
AND (pb.start_date IS NULL OR pb.start_date <= NOW())
AND (pb.end_date IS NULL OR pb.end_date >= NOW())
GROUP BY pb.product_id) product_badges_data', 'p.id_products = product_badges_data.product_id', 'left')
->where('p.product_status', '1')
->where('p.deleted_at', null)
->where('s.stock > 1')
->where('(s.stock - s.stock_keep) > 0')
->where('c.alias', 'pendatang-baru')
->where('c.alias_en', 'new-arrivals')
->group_by('p.id_products')
->order_by('p.created_at', 'DESC')
->limit(10);
$new_arrival_products = $this->db->get()->result_array();
echo json_encode($new_arrival_products);
}
public function get_carousels()
{
$carousels = $this->Carousel_banner_m->get_active_carousel();
echo json_encode($carousels);
}
public function get_banners()
{
$banners = $this->Top_banner_m->get_active_banners();
echo json_encode($banners);
}
public function get_brands()
{
$brands = $this->Brand_m->get_all_brands();
echo json_encode($brands);
}
public function get_testimonials()
{
$this->load->helper('url'); // agar base_url() bisa digunakan
$this->db->select('DISTINCT(stock.id_product) as id_product');
$this->db->from('stock');
$this->db->where('warehouse_id', 1);
$this->db->where('(stock - stock_keep) >', 0);
$available_products = $this->db->get_compiled_select();
$this->db->select('
product_review.id,
product_review.rating,
product_review.display_name as customer_name,
product_review.review as testimonial_text,
products.title as product_name,
products.alias as product_alias,
products.id_products as product_id,
customers.sex_type
');
$stock_subquery = "(SELECT SUM(stock - stock_keep)
FROM stock
WHERE stock.id_product = product_review.product_id
AND stock.warehouse_id = 1) as stock_sell";
$this->db->select($stock_subquery, FALSE);
$this->db->from('product_review');
$this->db->join('products', 'product_review.product_id = products.id_products');
$this->db->join('customers', 'product_review.customer_id = customers.id_customers');
$this->db->join("($available_products) as available_products", 'product_review.product_id = available_products.id_product');
$this->db->where('product_review.id IN (
SELECT MAX(pr.id)
FROM product_review pr
GROUP BY pr.product_id
)');
$this->db->order_by('product_review.id', 'DESC');
$this->db->limit(20);
$reviews = $this->db->get()->result();
$testimonials = [];
foreach ($reviews as $review) {
switch ($review->sex_type) {
case 'male':
$image = "https://storage.googleapis.com/laciasmara-photos/laciasmara_test/Laciasmara_testimonial/male.png";
break;
case 'female':
$image = "https://storage.googleapis.com/laciasmara-photos/laciasmara_test/Laciasmara_testimonial/female.png";
break;
default:
$image = "https://storage.googleapis.com/laciasmara-photos/laciasmara_test/Laciasmara_testimonial/others.png";
}
$testimonials[] = [
'customer_image' => $image,
'customer_name' => $review->customer_name,
'product_name' => $review->product_name,
'product_link' => base_url('product/' . $review->product_alias),
'star_rating' => $review->rating,
'testimonial_text' => $review->testimonial_text,
];
}
echo json_encode($testimonials);
}
public function get_search_overlay_data()
{
// Set JSON response header
header('Content-Type: application/json');
try {
// Ambil data popular categories dan trending searches
$popular_categories = $this->category_m->get_footer_popular_categories();
$trending_searches = $this->Statistic_m->get_trending_searches();
// Format response
$response = [
'status' => 'success',
'data' => [
'popular_categories' => $popular_categories,
'trending_searches' => $trending_searches
]
];
echo json_encode($response);
} catch (Exception $e) {
// Handle error
$response = [
'status' => 'error',
'message' => 'Gagal mengambil data'
];
echo json_encode($response);
}
}
/**
* Bulk update stock endpoint
* Method: POST
* Expected JSON format:
* {
* "stocks": [
* {"sku": "SKU001", "stock": 10},
* {"sku": "SKU002", "stock": 15}
* ]
* }
*/
public function bulk_stock_update()
{
header('Content-Type: application/json');
try {
// Hanya terima POST method
if ($this->input->method() !== 'post') {
$this->output
->set_status_header(405)
->set_output(json_encode([
'status' => 'error',
'message' => 'Method not allowed. Use POST method.'
]));
return;
}
// Ambil raw input JSON
$input = json_decode($this->input->raw_input_stream, true);
if (!$input || !isset($input['stocks']) || !is_array($input['stocks'])) {
$this->output
->set_status_header(400)
->set_output(json_encode([
'status' => 'error',
'message' => 'Invalid JSON format. Expected: {"stocks": [{"sku": "string", "stock": number}]}'
]));
return;
}
$stocks_data = $input['stocks'];
if (empty($stocks_data)) {
$this->output
->set_status_header(400)
->set_output(json_encode([
'status' => 'error',
'message' => 'Stocks data cannot be empty'
]));
return;
}
// Validasi format data
foreach ($stocks_data as $index => $stock_item) {
if (!isset($stock_item['sku']) || !isset($stock_item['stock'])) {
$this->output
->set_status_header(400)
->set_output(json_encode([
'status' => 'error',
'message' => "Invalid data format at index {$index}. Required: sku and stock"
]));
return;
}
if (!is_numeric($stock_item['stock']) || $stock_item['stock'] < 0) {
$this->output
->set_status_header(400)
->set_output(json_encode([
'status' => 'error',
'message' => "Invalid stock value at index {$index}. Stock must be a non-negative number"
]));
return;
}
}
// Proses bulk update
$result = $this->stocks_m->bulk_update_stock($stocks_data);
if ($result['success']) {
$this->output
->set_status_header(200)
->set_output(json_encode([
'status' => 'success',
'message' => 'Bulk stock update completed successfully',
'data' => [
'total_processed' => $result['total_processed'],
'successful_updates' => $result['successful_updates'],
'failed_updates' => $result['failed_updates'],
'details' => $result['details']
]
]));
} else {
$this->output
->set_status_header(500)
->set_output(json_encode([
'status' => 'error',
'message' => 'Bulk update failed',
'data' => [
'total_processed' => $result['total_processed'],
'successful_updates' => $result['successful_updates'],
'failed_updates' => $result['failed_updates'],
'details' => $result['details']
]
]));
}
} catch (Exception $e) {
log_message('error', 'Bulk stock update error: ' . $e->getMessage());
$this->output
->set_status_header(500)
->set_output(json_encode([
'status' => 'error',
'message' => 'Internal server error occurred'
]));
}
}
}