https://t.me/RX1948
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/models/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /var/www/laciasmara.com/public_html/shop/application/models/Stocks_m.php
<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Stocks_m extends CI_Model
{
    private $warehouse_id = 1;

    public function __construct()
    {
        parent::__construct();
        $this->load->database();
    }

    /**
     * Bulk update stock berdasarkan array SKU dan stock
     * 
     * @param array $stocks_data Array berisi data SKU dan stock baru
     * @return array Result dengan status dan detail update
     */
    public function bulk_update_stock($stocks_data)
    {
        $result = [
            'success' => true,
            'total_processed' => count($stocks_data),
            'successful_updates' => 0,
            'failed_updates' => 0,
            'details' => []
        ];

        // Start transaction
        $this->db->trans_start();

        foreach ($stocks_data as $stock_item) {
            $sku = trim($stock_item['sku']);
            $new_stock = intval($stock_item['stock']);

            try {
                // 1. Ambil id dan product_id dari product_details berdasarkan SKU
                $product_detail = $this->get_product_detail_by_sku($sku);

                if (!$product_detail) {
                    $result['failed_updates']++;
                    $result['details'][] = [
                        'sku' => $sku,
                        'status' => 'failed',
                        'message' => 'SKU not found in product_details'
                    ];
                    continue;
                }

                $id_product_detail = $product_detail['id'];
                $id_product = $product_detail['product_id'];

                // 2. Ambil data stock saat ini
                $current_stock_data = $this->get_current_stock($id_product, $id_product_detail);

                if (!$current_stock_data) {
                    // Jika belum ada record stock, buat baru
                    $stock_id = $this->create_stock_record($id_product, $id_product_detail, $new_stock);

                    if ($stock_id) {
                        // Log stock movement untuk stock baru
                        $remark = $this->generate_remark('BULK_INIT', $sku, ['new_stock' => $new_stock]);
                        $this->log_stock_movement($stock_id, '+', $new_stock, $new_stock, $remark);

                        $result['successful_updates']++;
                        $result['details'][] = [
                            'sku' => $sku,
                            'status' => 'success',
                            'message' => 'New stock record created',
                            'old_stock' => 0,
                            'new_stock' => $new_stock,
                            'change' => $new_stock
                        ];
                    } else {
                        $result['failed_updates']++;
                        $result['details'][] = [
                            'sku' => $sku,
                            'status' => 'failed',
                            'message' => 'Failed to create stock record'
                        ];
                    }
                    continue;
                }

                $stock_id = $current_stock_data['id'];
                $current_stock = intval($current_stock_data['stock']);

                // Skip jika stock sama
                if ($current_stock == $new_stock) {
                    $result['successful_updates']++;
                    $result['details'][] = [
                        'sku' => $sku,
                        'status' => 'success',
                        'message' => 'Stock unchanged',
                        'old_stock' => $current_stock,
                        'new_stock' => $new_stock,
                        'change' => 0
                    ];
                    continue;
                }

                // 3. Update stock
                $update_success = $this->update_stock($stock_id, $new_stock);

                if (!$update_success) {
                    $result['failed_updates']++;
                    $result['details'][] = [
                        'sku' => $sku,
                        'status' => 'failed',
                        'message' => 'Failed to update stock'
                    ];
                    continue;
                }

                // 4. Hitung perubahan dan tentukan type
                $stock_change = abs($new_stock - $current_stock);
                $movement_type = ($new_stock > $current_stock) ? '+' : '-';

                // 5. Log stock movement
                $remark = $this->generate_remark('BULK_UPDATE', $sku, [
                    'old_stock' => $current_stock,
                    'new_stock' => $new_stock,
                    'type' => $movement_type,
                    'change' => $stock_change
                ]);

                $movement_success = $this->log_stock_movement(
                    $stock_id,
                    $movement_type,
                    $stock_change,
                    $new_stock,
                    $remark
                );

                if ($movement_success) {
                    $result['successful_updates']++;
                    $result['details'][] = [
                        'sku' => $sku,
                        'status' => 'success',
                        'message' => 'Stock updated successfully',
                        'old_stock' => $current_stock,
                        'new_stock' => $new_stock,
                        'change' => ($movement_type === '+' ? $stock_change : -$stock_change)
                    ];
                } else {
                    $result['failed_updates']++;
                    $result['details'][] = [
                        'sku' => $sku,
                        'status' => 'failed',
                        'message' => 'Stock updated but failed to log movement'
                    ];
                }
            } catch (Exception $e) {
                $result['failed_updates']++;
                $result['details'][] = [
                    'sku' => $sku,
                    'status' => 'failed',
                    'message' => 'Exception: ' . $e->getMessage()
                ];

                log_message('error', "Stock update error for SKU {$sku}: " . $e->getMessage());
            }
        }

        // Complete transaction
        $this->db->trans_complete();

        if ($this->db->trans_status() === FALSE) {
            $result['success'] = false;
            log_message('error', 'Database transaction failed during bulk stock update');
        }

        // Set overall success based on whether any updates failed
        if ($result['failed_updates'] > 0) {
            $result['success'] = false;
        }

        return $result;
    }

    /**
     * Ambil detail produk berdasarkan SKU
     */
    private function get_product_detail_by_sku($sku)
    {
        $this->db->select('id, product_id, sku');
        $this->db->where('sku', $sku);
        $query = $this->db->get('product_details');

        return $query->row_array();
    }

    /**
     * Ambil data stock saat ini
     */
    private function get_current_stock($id_product, $id_product_detail)
    {
        $this->db->select('id, stock');
        $this->db->where('id_product', $id_product);
        $this->db->where('id_product_detail', $id_product_detail);
        $this->db->where('warehouse_id', $this->warehouse_id);
        $query = $this->db->get('stock');

        return $query->row_array();
    }

    /**
     * Buat record stock baru
     */
    private function create_stock_record($id_product, $id_product_detail, $stock)
    {
        $data = [
            'id_product' => $id_product,
            'id_product_detail' => $id_product_detail,
            'warehouse_id' => $this->warehouse_id,
            'stock' => $stock,
            'stock_keep' => 0,
            'stock_reject' => 0,
            'stock_sample' => 0
        ];

        if ($this->db->insert('stock', $data)) {
            return $this->db->insert_id();
        }

        return false;
    }

    /**
     * Update stock
     */
    private function update_stock($stock_id, $new_stock)
    {
        $this->db->where('id', $stock_id);
        return $this->db->update('stock', ['stock' => $new_stock]);
    }

    /**
     * Log stock movement
     */
    public function log_stock_movement($stock_id, $type, $stock_change, $total_stock, $remark, $user_name = 'System')
    {
        $data = [
            'stock_id' => $stock_id,
            'type' => $type,
            'stock_change' => $stock_change,
            'stock_type' => 'stock',
            'remark' => $remark,
            'total' => $total_stock,
            'name' => $user_name,
            'datetime' => date('Y-m-d H:i:s')
        ];

        return $this->db->insert('stock_movement', $data);
    }

    /**
     * Get stock data dengan SKU untuk manual adjustment
     */
    public function get_stock_with_sku($product_detail_id, $warehouse_id)
    {
        $this->db->select('s.id as stock_id, s.id_product, s.stock, s.stock_keep, s.stock_reject, s.stock_sample, pd.sku');
        $this->db->from('stock s');
        $this->db->join('product_details pd', 'pd.id = s.id_product_detail');
        $this->db->where('s.id_product_detail', $product_detail_id);
        $this->db->where('s.warehouse_id', $warehouse_id);

        $query = $this->db->get();
        return $query->row_array();
    }

    /**
     * Update stock berdasarkan tipe stock tertentu
     */
    public function update_stock_by_type($stock_id, $stock_type, $new_value)
    {
        // Validasi stock_type yang diizinkan
        $allowed_types = ['stock', 'stock_keep', 'stock_reject', 'stock_sample'];
        if (!in_array($stock_type, $allowed_types)) {
            return false;
        }

        $update_data = [$stock_type => $new_value];

        $this->db->where('id', $stock_id);
        return $this->db->update('stock', $update_data);
    }


    /**
     * Log stock movement dengan dukungan berbagai tipe stock dan tabel movement
     */
    public function log_stock_movement_by_type($stock_id, $type, $stock_change, $total_stock, $remark, $stock_type = 'stock', $user_name = 'System')
    {
        // Tentukan tabel movement berdasarkan stock_type
        $movement_tables = [
            'stock' => 'stock_movement',
            'stock_keep' => 'stock_movement_keep',
            'stock_reject' => 'stock_movement_reject',
            'stock_sample' => 'stock_movement_sample'
        ];

        $movement_table = isset($movement_tables[$stock_type]) ? $movement_tables[$stock_type] : 'stock_movement';

        $data = [
            'stock_id' => $stock_id,
            'type' => $type,
            'stock_change' => $stock_change,
            'stock_type' => $stock_type,
            'remark' => $remark,
            'total' => $total_stock,
            'name' => $user_name,
            'datetime' => date('Y-m-d H:i:s')
        ];

        return $this->db->insert($movement_table, $data);
    }

    /**
     * Update generate_remark method untuk mendukung lebih banyak scenario
     */
    public function generate_remark($action, $sku, $details = [])
    {
        $timestamp = date('Y-m-d H:i:s');

        switch ($action) {
            case 'BULK_INIT':
                return "STOCK INITIALIZATION - SKU: {$sku} | Initial stock set to {$details['new_stock']} units | Created by Admin IT via Bulk Stock Update API | {$timestamp}";

            case 'BULK_UPDATE':
                return "STOCK ADJUSTMENT - SKU: {$sku} | Previous: {$details['old_stock']} units | New: {$details['new_stock']} units | Change: {$details['type']}{$details['change']} units | Reason: Bulk stock update via API | Updated by Admin IT | {$timestamp}";

            case 'SALES_ORDER':
                return "STOCK REDUCTION - SKU: {$sku} | Sold: {$details['qty']} units | Order: {$details['order_no']} | Customer: {$details['customer']} | Remaining: {$details['remaining']} units | {$timestamp}";

            case 'PURCHASE':
                return "STOCK ADDITION - SKU: {$sku} | Received: {$details['qty']} units | PO: {$details['po_no']} | Supplier: {$details['supplier']} | Total: {$details['total']} units | {$timestamp}";

            case 'MANUAL_ADJUSTMENT':
                $stock_type_label = $this->get_stock_type_description($details['stock_type']);
                return "MANUAL ADJUSTMENT - SKU: {$sku} | Stock Type: {$stock_type_label} | Previous: {$details['old_value']} units | New: {$details['total']} units | Change: {$details['type']}{$details['change']} units | Adjusted by: {$details['user']} | Reason: {$details['reason']} | {$timestamp}";

            case 'TRANSFER_OUT':
                return "STOCK TRANSFER OUT - SKU: {$sku} | Transferred: {$details['qty']} units | To Warehouse: {$details['to_warehouse']} | Transfer ID: {$details['transfer_id']} | Remaining: {$details['remaining']} units | {$timestamp}";

            case 'TRANSFER_IN':
                return "STOCK TRANSFER IN - SKU: {$sku} | Received: {$details['qty']} units | From Warehouse: {$details['from_warehouse']} | Transfer ID: {$details['transfer_id']} | Total: {$details['total']} units | {$timestamp}";

            case 'ORDER_CANCELLED':
                return "ORDER CANCELLATION - SKU: {$sku} | Returned: {$details['qty']} units | Order: {$details['order_no']} | Customer: {$details['customer']} | Stock restored to: {$details['total']} units | {$timestamp}";

            default:
                return "STOCK MOVEMENT - SKU: {$sku} | Action: {$action} | Details: " . json_encode($details) . " | {$timestamp}";
        }
    }

    /**
     * Helper method untuk deskripsi stock type
     */
    private function get_stock_type_description($stock_type)
    {
        $descriptions = [
            'stock' => 'Regular Stock',
            'stock_keep' => 'Keep Stock',
            'stock_reject' => 'Reject Stock',
            'stock_sample' => 'Sample Stock'
        ];

        return isset($descriptions[$stock_type]) ? $descriptions[$stock_type] : 'Unknown Stock Type';
    }

    /**
     * Get stock movement history dengan pagination dan filter
     */
    public function get_stock_movement_history($filters = [], $limit = 50, $offset = 0)
    {
        $this->db->select('sm.*, pd.sku, p.product_name');
        $this->db->from('stock_movement sm');
        $this->db->join('stock s', 's.id = sm.stock_id');
        $this->db->join('product_details pd', 'pd.id = s.id_product_detail');
        $this->db->join('products p', 'p.id = s.id_product');

        // Apply filters
        if (!empty($filters['sku'])) {
            $this->db->where('pd.sku', $filters['sku']);
        }

        if (!empty($filters['stock_type'])) {
            $this->db->where('sm.stock_type', $filters['stock_type']);
        }

        if (!empty($filters['warehouse_id'])) {
            $this->db->where('s.warehouse_id', $filters['warehouse_id']);
        }

        if (!empty($filters['date_from'])) {
            $this->db->where('DATE(sm.datetime) >=', $filters['date_from']);
        }

        if (!empty($filters['date_to'])) {
            $this->db->where('DATE(sm.datetime) <=', $filters['date_to']);
        }

        $this->db->order_by('sm.datetime', 'DESC');
        $this->db->limit($limit, $offset);

        $query = $this->db->get();
        return $query->result_array();
    }
}

https://t.me/RX1948 - 2025