Блокировки транзакций с CodeIgniter в MySQL - PullRequest
0 голосов
/ 30 января 2020

У меня есть некоторые проблемы с транзакциями, которые частично или совсем не работают в Codeigniter. Я работаю с базой кода, которая имеет много проверок и дополнительных проверок, которые у меня нет времени, чтобы удалить, и я пытаюсь исправить это, чтобы предотвратить «Потерянное обновление», так как несколько человек могут быть обновление той же информации.

Я попробовал функцию транзакций Codeigniters, но, похоже, она не работает. Поэтому я попробовал транзакции MySQL, и это непредсказуемо или не работает вообще. Я делаю это неправильно?

Я включил только часть кодовой базы, потому что между двумя файлами содержится около 6000 строк кода.

Контроллер

    // GET
public function index_get( $sales_order_id = null )
{
    // GET PARAMS.
    $data = $this->get();

    if( $sales_order_id !== null && (int) $sales_order_id > 0 )
    {
        // Get id specified sales_order.
        $sales_order = $this->get_all_sales_order_data( $sales_order_id );

        if( $sales_order === null )
        {
            $this->response(['error' => 'No record found.'], REST_Controller::HTTP_NOT_FOUND);
        }

        $response = ['sales_order' => $sales_order];
        $this->response($response, REST_Controller::HTTP_OK);
    }
    else
    {
        if( !empty($data) && isset($data['search_string']) )
        {
            $search_string  = $data['search_string'];
            $limit_per_page = $data['limit_per_page'];
            $offset         = $limit_per_page * ($data['page_number'] - 1);
            $outwards_type  = $data['outwards_type'];
            $status         = $data['status'];
            $is_deleted     = $data['is_deleted'] == 'true' ? 1 : 0;

            // Get all sales_orders.
            $sales_orders = $this->Model_sales_orders->search_sales_orders( $search_string, $offset, $limit_per_page, $outwards_type, $status, $is_deleted );

            $results_count = $this->Model_sales_orders->count_search_results( $search_string, $outwards_type, $status, $is_deleted );

            // Get all shipment lines for orders.
            foreach( $sales_orders as $order )
            {
                $order->combined        = $this->Model_sales_orders->get_reference_numbers_of_combined($order->id);
                $order->shipments       = $this->Model_shipments->get_shipments_by_sales_order($order->id);
                $order->shipment_lines  = $this->Model_shipments->get_shipment_lines_by_sales_order($order->id);
            }

            $response = ['sales_orders' => $sales_orders, 'results_count' => $results_count];
            $this->response($response, REST_Controller::HTTP_OK);
        }
        else
        {
            // Get all sales_orders.
            $sales_orders = $this->Model_sales_orders->get_sales_orders();

            $response = ['sales_orders' => $sales_orders];
            $this->response($response, REST_Controller::HTTP_OK);
        }
    }
}

// POST
public function index_post()
{
    // Less than Account Manager - Level 4.
    if( $this->user->user_level < 4 )
    {
        $response = ['error' => 'No permission to authorise this action!'];
        $this->response($response, REST_Controller::HTTP_UNAUTHORIZED);
    }

    // Get post data.
    $data = $this->post();
    $user_id = $this->user->id;
    $organisation = $this->database->organisation_code;
    $org_id = $this->database->organisation_id;

    // Set data for form validation.
    $this->form_validation->set_data($data);


    // Is unique callback.
    $is_unique = [];
    $is_unique[0] = '|callback_order_number_check';
    $is_unique[1] = '|callback_client_reference_check';

    // Set validation rules.
    $this->form_validation->set_rules('order_number', 'Order Number', 'required|trim' . $is_unique[0]);
    $this->form_validation->set_rules('client_reference', 'Client Reference', 'trim' . $is_unique[1]);

    // Check if form validation passed.
    if( $this->form_validation->run() === FALSE )
    {
        // Create response.
        $response = ['error' => validation_errors('<li>', '</li>')];
        $this->response($response, REST_Controller::HTTP_BAD_REQUEST);
    }
    else
    {

        $this->Model_sales_orders->insert_sales_order($data, $user_id, $organisation, $org_id);

        $response = ['message' => 'Sales Order created', 'sales_order_id' => $data];
        $this->response($response, REST_Controller::HTTP_OK);
    }
}



// PUT METHOD.
public function index_put( $sales_order_id = null )
{
    if( $sales_order_id !== null )
    {

        // GET PARAMS.
        $input = $this->put();
        $user_id = $this->user->id;


        //Validation Method 2

        $data = $this->Model_sales_orders->update_sales_order($sales_order_id, $input, $user_id);

        if ($data === FALSE){
            $response = ['error' => validation_errors('<li>', '</li>')];
            $this->response($response, REST_Controller::HTTP_BAD_REQUEST);
        } else {
            $response = ['message' => 'Updated successfully', 'sales_order' => $data];
            $this->response($response, REST_Controller::HTTP_OK);
        }

    }
    else
    {
        $response = ['error' => 'No id provided'];
        $this->response($response, REST_Controller::HTTP_NOT_FOUND);
    }

}

Модель

/*
 * Update sales_order.
 *
 * @param int $sales_order_id - Sales_order ID.
 * @param array $sales_order_data - Sales_order data array.
 * @return bool - Return TRUE or FALSE.
 *
 */

public function update_sales_order($sales_order_id, $data, $user_id)
{
    // Select DB.
    $this->db->db_select($this->selected_db);

    //// Less than Account Manager - Level 4.
    //if( $this->user->user_level < 4 )
    //{
    //  $response = ['error' => 'No permission to authorise this action!'];
    //  $this->response($response, REST_Controller::HTTP_UNAUTHORIZED);
    //}

    // Check to see if sales order is finalised already.
    if ($this->is_finalised($sales_order_id) == true) {
        $response = ['error' => 'ERROR: Sales order has already been finalised'];
        return $this->response($response, REST_Controller::HTTP_CONFLICT);
    }


    // Sales order data.
    $sales_order_data = [
        'job_id' => element('job_id', $data, ''),
        'consignee_id' => element('consignee_id', $data, 0),
        'carrier_id' => element('carrier_id', $data, 0),
        'carrier_account_number' => element('carrier_account_number', $data, ''),
        'delivery_instructions' => element('delivery_instructions', $data, ''),
        'order_number' => element('order_number', $data, ''),
        'client_reference' => element('client_reference', $data, ''),
        'date_posted' => date_prepped(element('date_posted', $data, '')),
        'date_required' => date_prepped(element('date_required', $data, '')),
        'shipping_method' => element('shipping_method', $data, ''),
        'notes' => element('notes', $data, ''),
        'total_weight_ordered' => element('total_weight_ordered', $data, 0),
        'total_cubic_ordered' => element('total_cubic_ordered', $data, 0),
        'total_units_ordered' => element('total_units_ordered', $data, 0),
        'total_weight_picked' => element('total_weight_picked', $data, 0),
        'total_cubic_picked' => element('total_cubic_picked', $data, 0),
        'total_units_picked' => element('total_units_picked', $data, 0),
        'total_cartons' => element('total_cartons', $data, 0),
        'total_outers' => element('total_outers', $data, 0),
        'total_pallets' => element('total_pallets', $data, 0),
        'uniform_pallets_picked' => element('uniform_pallets_picked', $data, 0),
        'pick_time_taken' => element('pick_time_taken', $data, 0),
        'hoist_unloads' => element('hoist_unloads', $data, 0),
        'is_urgent' => element('is_urgent', $data, false),
        'is_finalised' => element('is_finalised', $data, false),
        'picked_by' => element('picked_by', $data, ''),
        'modified_by' => $user_id,
        'datetime_expected_pickup' => datetime_prepped(element('datetime_expected_pickup', $data, '')),
        'datetime_pick_started' => datetime_prepped(element('datetime_pick_started', $data, '')),
        'datetime_pick_completed' => datetime_prepped(element('datetime_pick_completed', $data, ''))
    ];

    // Edit combined if it has been modified.
    if (isset($data['combined_modified']) && $data['combined_modified'] == true) {
        $orders_combined = $this->get_sales_order_combined($sales_order_id);
        $orders_ids = [];

        foreach ($orders_combined as $order) {
            $orders_ids[] = $order->order_combined_id;
        }

        $removed_combined = array_diff($orders_ids, $data['combined']);
        $new_combined = array_diff($data['combined'], $orders_ids);

        if (!empty($removed_combined)) {
            $this->delete_sales_order_combined($removed_combined);
        }
    }

    // Process new combined
    if (!empty($new_combined)) {
        foreach ($new_combined as $order_id) {
            $this->insert_sales_order_combined([
                'sales_order_id' => $sales_order_id,
                'order_combined_id' => $order_id
            ]);
        }
    }

    // If is packed then update status accordingly.
    if (element('is_picked', $data, false) == true) {
        $sales_order_data['status'] = 2; // Goods Picked.
        $sales_order_data['is_picked'] = true;

        foreach ($data['picks'] as $pick) {
            if (element('is_picked', $pick, false) == false) {
                $sales_order_data['status'] = 1; // Pending Pick.
                break;
            }
        }
    }

    // If is packed then update status accordingly.
    if (element('is_packed', $data, false) == true) {
        $sales_order_data['status'] = 3; // Goods Packed.
        $sales_order_data['is_packed'] = true;
    }

    // If finalised.
    if (element('is_finalised', $data, false) == true) {
        $sales_order_data['status'] = 5; // Pending Charges.
        $sales_order_data['is_shipped'] = true;
        $sales_order_data['datetime_finalised'] = date('Y-m-d H:i:s');

        // Release all committed quantity from picks.
        $this->release_committed_quantity($data['picks']);
    }

    // Delete sales order lines.
    if (!empty($data['removed_lines'])) {
        $this->delete_sales_order_lines($data['removed_lines']);
    }

    // Delete sales order fees.
    if (!empty($data['removed_fees'])) {
        $this->delete_sales_order_fees($data['removed_fees']);
    }

    // Delete pick lines.
    if (!empty($data['removed_picks'])) {
        // Unallocate committed inventory.
        $this->unallocate_committed_inventory($data['removed_picks']);

        $this->delete_sales_order_picks($data['removed_picks']);
    }

    // Delete services.
    if (!empty($data['removed_services'])) {
        $this->delete_sales_order_services($data['removed_services']);
    }

    // Delete pallets.
    if (!empty($data['removed_pallets'])) {
        $this->delete_sales_order_pallets($data['removed_pallets']);
    }

    // Delete packs.
    if (!empty($data['removed_packs'])) {
        $this->Model_packs->delete_packs($data['removed_packs']);
    }

    // Delete pack lines.
    if (!empty($data['removed_pack_lines'])) {
        $this->Model_packs->delete_pack_lines($data['removed_pack_lines']);
    }

    // Delete shipments.
    if (!empty($data['removed_shipments'])) {
        $this->Model_shipments->delete_shipments($data['removed_shipments']);
    }

    // Delete shipment lines.
    if (!empty($data['removed_shipment_lines'])) {
        $this->Model_shipments->delete_shipment_lines($data['removed_shipment_lines']);
    }

    // Process lines.
    if (!empty($data['lines'])) {
        foreach ($data['lines'] as $line) {
            if (isset($line['id'])) {
                // Update line.
                $this->update_line($sales_order_id, $line, $user_id);
            } else {
                // Create line.
                $this->create_line($sales_order_id, $line, $user_id);
            }

            if (element('is_finalised', $data, false) == true) {
                if (element('parent_id', $line, 0) != 0) {
                    continue;
                }

                $cost_current = $this->Model_products->get_product_cost_current(element('product_id', $line, 0));
                $stock_amount = $cost_current * element('quantity_picked', $line, 0);

                // Insert ledger account transaction.
                $this->client_ledger->insert_ledger_transaction([
                    'ledger_account_id' => $this->client_ledger->get_ledger_account_id_by_code('9150'),
                    'transaction_type' => 'Order',
                    'reference_number' => element('reference_number', $data, ''),
                    'date_posted' => date('Y-m-d'),
                    'amount_type' => 'Credit',
                    'amount_total' => $stock_amount,
                    'created_by' => $user_id,
                    'modified_by' => $user_id
                ]);

                // Insert ledger account transaction.
                $this->client_ledger->insert_ledger_transaction([
                    'ledger_account_id' => $this->client_ledger->get_ledger_account_id_by_code('2104'),
                    'transaction_type' => 'Order',
                    'reference_number' => element('reference_number', $data, ''),
                    'date_posted' => date('Y-m-d'),
                    'amount_type' => 'Debit',
                    'amount_total' => $stock_amount,
                    'created_by' => $user_id,
                    'modified_by' => $user_id
                ]);
            }
        }
    }

    // Process fees.
    if (!empty($data['fees'])) {
        foreach ($data['fees'] as $fee) {
            if (isset($fee['id'])) {
                // Update fee.
                $this->update_fee($sales_order_id, $fee, $user_id);
            } else {
                // Create fee.
                $this->create_fee($sales_order_id, $fee, $user_id);
            }
        }
    }

    // Process lines.
    if (!empty($data['picks'])) {
        foreach ($data['picks'] as $pick) {
            if (isset($pick['id'])) {
                // Update pick.
                $this->update_pick($sales_order_id, $pick, $user_id);
            } else {
                // Create pick.
                $this->create_pick($sales_order_id, $pick, $user_id);
            }
        }
    }

    // Process packs.
    if (!empty($data['packs'])) {
        foreach ($data['packs'] as $pack) {
            if (isset($pack['id'])) {
                // Update pack.
                $this->update_pack($pack, $user_id);
            } else {
                // Create pack.
                $pack_id = $this->create_pack($pack, $user_id);
            }
        }
    }

    // Process packs.
    if (!empty($data['shipments'])) {
        foreach ($data['shipments'] as $shipment) {
            if (isset($shipment['id'])) {
                // Update shipment.
                $this->update_shipment($sales_order_id, $shipment, $user_id);
            } else {
                // Create shipment.
                $shipment_id = $this->create_shipment($sales_order_id, $shipment, $user_id);
            }
        }
    }

    // Process services.
    if (!empty($data['services'])) {
        foreach ($data['services'] as $service) {
            if (isset($service['id'])) {
                // Update service.
                $this->update_service($sales_order_id, $service, $user_id);
            } else {
                // Create service.
                $this->create_service($sales_order_id, $service, $user_id);
            }
        }
    }

    // Process pallets.
    if (!empty($data['pallets'])) {
        foreach ($data['pallets'] as $pallet) {
            if (isset($pallet['id'])) {
                // Update pallet.
                $this->update_pallet($sales_order_id, $pallet, $user_id);
            } else {
                // Create pallet.
                $this->create_pallet($sales_order_id, $pallet, $user_id);
            }
        }
    }

    if (!empty($data['billing'])) {
        ## Billing data.
        $billing_data = [
            'copy_shipping' => element('copy_shipping', $data['billing'], false),
            'contact_first_name' => element('contact_first_name', $data['billing'], ''),
            'contact_last_name' => element('contact_last_name', $data['billing'], ''),
            'contact_full_name' => element('contact_full_name', $data['billing'], ''),
            'company' => element('company', $data['billing'], ''),
            'phone' => element('phone', $data['billing'], ''),
            'ddi' => element('ddi', $data['billing'], ''),
            'mobile' => element('mobile', $data['billing'], ''),
            'fax' => element('fax', $data['billing'], ''),
            'email' => element('email', $data['billing'], ''),
            'address1' => element('address1', $data['billing'], ''),
            'address2' => element('address2', $data['billing'], ''),
            'suburb' => element('suburb', $data['billing'], ''),
            'city' => element('city', $data['billing'], ''),
            'postcode' => element('postcode', $data['billing'], ''),
            'state' => element('state', $data['billing'], ''),
            'country' => element('country', $data['billing'], ''),
            'port_code' => element('port_code', $data['billing'], ''),
            'un_locode' => element('un_locode', $data['billing'], ''),
            'is_rural' => element('is_rural', $data['billing'], false),
            'override' => element('override', $data['billing'], false)
        ];

        $this->update_sales_order_billing($sales_order_id, $billing_data);
    }

    if (!empty($data['shipping'])) {
        ## Shipping data.
        $shipping_data = [
            'copy_billing' => element('copy_billing', $data['shipping'], false),
            'contact_first_name' => element('contact_first_name', $data['shipping'], ''),
            'contact_last_name' => element('contact_last_name', $data['shipping'], ''),
            'contact_full_name' => element('contact_full_name', $data['shipping'], ''),
            'company' => element('company', $data['shipping'], ''),
            'phone' => element('phone', $data['shipping'], ''),
            'ddi' => element('ddi', $data['shipping'], ''),
            'mobile' => element('mobile', $data['shipping'], ''),
            'fax' => element('fax', $data['shipping'], ''),
            'email' => element('email', $data['shipping'], ''),
            'address1' => element('address1', $data['shipping'], ''),
            'address2' => element('address2', $data['shipping'], ''),
            'suburb' => element('suburb', $data['shipping'], ''),
            'city' => element('city', $data['shipping'], ''),
            'postcode' => element('postcode', $data['shipping'], ''),
            'state' => element('state', $data['shipping'], ''),
            'country' => element('country', $data['shipping'], ''),
            'port_code' => element('port_code', $data['shipping'], ''),
            'un_locode' => element('un_locode', $data['shipping'], ''),
            'is_rural' => element('is_rural', $data['shipping'], false),
            'override' => element('override', $data['shipping'], false)
        ];

        $this->update_sales_order_shipping($sales_order_id, $shipping_data);
    }
    // Check if any lines are on shortfall and set status to 0. Also return response.
    if (element('allow_backorders', $data, false) == true) {

        // check if sales order has shortfall.
        $has_shortfall = $this->Model->check_for_shortfall($sales_order_id);

        if ($has_shortfall == true && element('is_finalised', $data, false) == true) {
            // Create backorder.
            $this->create_backorder($sales_order_id, $user_id);
        }
    }

    if (element('is_finalised', $data, false) == true) {
        //$this->create_order_in_eship( $data );
    }

    // Set timestamp.
    $sales_order_data['datetime_modified'] = date('Y-m-d H:i:s');

    // Process update query and return results.
    $this->db->where('id', $sales_order_id);
    $result = $this->db->update($this->table_name, $sales_order_data);

    $this->db->trans_complete();
    return $result;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...