У меня есть некоторые проблемы с транзакциями, которые частично или совсем не работают в 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;
}