<?php


function compareBySequence($a, $b)
{
    return $a['sequence'] - $b['sequence'];
}

$total_all_stock_records = 0.00;
$ledger_total_amount = 0.00;
$total_new_all_stock_records = 0.00;

$stock_record = array();
$taxamount = 0.00;
$base_price = 0.00;
$total_amount = 0.00;
// sanitize stockrecord
// traverse through each stock item element
// go through their ledger_entries 
// depending on id_add (true / false) and transctiontype (purchase ), we will insert them into creditrecord or debitrecord

$transaction_record_rows = array();

$transaction_record_rows = [];

$creditrecord = [];
$debitrecord = [];
$stockrecord = $postdata['stockrecord'];
$stockrecord = json_decode($stockrecord, true);
$updatedcreditrecord = [];
$updateddebitrecord = [];
$creditrecord = $postdata['creditrecord'];
$creditrecord = json_decode($creditrecord, true);
$debitrecord = $postdata['debitrecord'];
$debitrecord = json_decode($debitrecord, true);
$base_price_total = 0; // total of all base stock prices
$stock_final_price_total = 0; // final amount of bill

if ($stockrecord != null and is_array($stockrecord)) {

    // print_r($stockrecord);
    // die();

    foreach ($stockrecord as $data) {

        $description = (isset($data['description']) and !empty($data['description'])) ? trim($data['description']) : null;
        $stock_id = $data['stock_id'];
        //  $per_price = (isset($data['per_price']) and !empty($data['per_price'])  and is_numeric($data['per_price']) and (floatval($data['per_price']) > 0)) ? abs((float)$data['per_price']) : errorreturn("Amount cannot be zero");
        $per_price = (isset($data['per_price']) and (is_numeric($data['per_price']) or $data['per_price'] === '0') and (floatval($data['per_price']) >= 0)) ? abs((float)$data['per_price']) : errorreturn("Amount cannot be negative");

        $qty = (isset($data['qty']) and !empty($data['qty']) and (floatval($data['qty']) > 0)) ? abs((float)$data['qty']) : errorreturn("Quantity cannot be zero"); // not necessary available (incase of inventory_applicable == false, you shall not receive this, default it to 1 in that case)

        $batch_details = (isset($data['batch_details']) and is_array($data['batch_details']) and !empty($data['batch_details'])) ? $data['batch_details'] : null;
        $inventory_batch_details = [];


        $base_price_specific = $per_price * $qty; // specific to stock
        // echo $base_price_specific;die();
        $stock_price_specific = $base_price_specific; // specific to stock and ledgers added
        $stock_final_price_total +=  $stock_price_specific;
        $base_price_total += $base_price_specific;

        $res = $specific_db_conn->prepare("SELECT id,current_qty,unit_id,boolean_inventory, stock_name FROM inventory_stockdetails WHERE id = ? and  workspace_id  =? and company_id= ? and  branch_id =? and book_id =?");
        $res->execute(array($stock_id, $workspace_id, $company_id, $branch_id, $book_id));
        $result1 = $res->fetchAll();
        if (count($result1) != 1) {
            errorreturn('stock items found.');
        } else {

            $stock_name = $result1[0]['stock_name'];
            $existing_current_qty = $result1[0]['current_qty'];
            $boolean_inventory = $result1[0]['boolean_inventory'];

            // check if ledger entries is  isset and array
            if (isset($data['ledger_entries'])) {
                $ledger_entries = $data['ledger_entries'];
            } else {
                $ledger_entries = null;
            }

            if ($ledger_entries !=  null and is_array($ledger_entries)) {
                // sort ledger entries
                usort($ledger_entries, 'compareBySequence');
                $temp_base_stock = $base_price_specific; // used to calculate rows
                $temp_adjusted_stock = $base_price_specific; // used to calculate rows

                $last_mainledgerhead = getLedgerSpecificLedgerhead($specific_db_conn, $ledger_entries[0]['ledgerid'], $workspace_id, $company_id, $branch_id, $book_id);
                foreach ($ledger_entries as $data) {

                    $ledgerid = $data['ledgerid'];
                    $is_add = $data['is_add'];
                    $sequence = $data['sequence'];
                    $adjusted_type = $data['adjusted_type'];
                    $amount = $data['total_amount'];
                    $current_temp_main_ledgerhead = getLedgerSpecificLedgerhead($specific_db_conn, $ledgerid, $workspace_id, $company_id, $branch_id, $book_id);

                    if (($last_mainledgerhead != 'Duties & Taxes' && $current_temp_main_ledgerhead == 'Duties & Taxes') || ($last_mainledgerhead == 'Duties & Taxes' && $current_temp_main_ledgerhead != 'Duties & Taxes')) {
                        $temp_base_stock = $temp_adjusted_stock;
                    }
                    $last_mainledgerhead = $current_temp_main_ledgerhead;

                    $percentage = (isset($data['percentage']) and !empty($data['percentage'])) ? trim($data['percentage']) : null;



                    if ($adjusted_type == '0') { // work on base_price_specific
                        if ($percentage != null) {
                            $taxamount = ((floatval($temp_base_stock) * floatval($percentage) / 100));
                        } else {
                            $taxamount = $amount;
                        }

                        if ($is_add == '1') {
                            $a = array('ledgerid' => $ledgerid, 'amount' => $taxamount);
                            array_push($updateddebitrecord, $a);
                            $stock_price_specific +=  $taxamount;
                            $stock_final_price_total +=  $taxamount;
                        } else {
                            $a = array('ledgerid' => $ledgerid, 'amount' => $taxamount);
                            array_push($updatedcreditrecord,  $a);
                            $stock_price_specific -=  $taxamount;
                            $stock_final_price_total -=  $taxamount;
                        }
                    } else {

                        if ($percentage != null) {
                            $taxamount = ($temp_adjusted_stock) * ($percentage) / 100;
                        } else {
                            $taxamount = $amount;
                        }
                        if ($is_add == '1') {
                            $a =  array('ledgerid' => $ledgerid, 'amount' => $taxamount);
                            array_push($updateddebitrecord, $a);
                            $stock_price_specific +=  $taxamount;
                            $stock_final_price_total +=  $taxamount;
                        } else {
                            $a =  array('ledgerid' => $ledgerid, 'amount' => $taxamount);
                            array_push($updatedcreditrecord,  $a);
                            $stock_price_specific -=  $taxamount;
                            $stock_final_price_total -=  $taxamount;
                        }
                    }

                    if ($is_add == '1') {
                        $temp_adjusted_stock += $taxamount;
                    } else $temp_adjusted_stock -= $taxamount;
                }
            } else {
                $ledger_entries = null;
            }

            if ($boolean_inventory == 1) {

                $single_empty_barcode = 0;
                $unique_barcode_counter = 0;
                $existing_barcode_array = [];
                if ($batch_details != null) {
                    $qty_verified = 0;
                    foreach ($batch_details as $temp) {

                        // where will you check that only one stock_barcode_uin can be empty not more
                        $stock_barcode_uin = (isset($temp['stock_barcode_uin']) and !empty($temp['stock_barcode_uin'])) ? trim($temp['stock_barcode_uin']) : null;

                        if (empty($stock_barcode_uin) or $stock_barcode_uin == $stock_name) {
                            $single_empty_barcode++;
                        }

                        // check for duplicacy and uniqueness
                        if (in_array($stock_barcode_uin, $existing_barcode_array)) {
                            errorreturn("All barcodes for a stock item batch should be unique.");
                        }
                        $expiry = (isset($temp['expiry']) and !empty($temp['expiry'])) ? trim($temp['expiry']) : null;
                        $mfg_date = (isset($temp['mfg_date']) and !empty($temp['mfg_date'])) ? trim($temp['mfg_date']) : null;
                        $remarks = (isset($temp['remarks']) and !empty($temp['remarks'])) ? trim($temp['remarks']) : null;
                        $qty_verified += $temp['qty'];

                        $inventory_batch_details[] = array(
                            'stock_barcode_uin' => $stock_barcode_uin, 'type' => $transactiontype, 'rate' => ($base_price_specific / $temp['qty']), 'qty' => $temp['qty'], 'expiry' => $expiry, 'mfg_date' => $mfg_date, 'amount' => ($base_price_specific / $qty) * $temp['qty'], 'remarks' => $remarks
                        );
                    }
                    if ($single_empty_barcode > 1) {
                        errorreturn("Only one particular for barcode can be left empty.");
                    }

                    if ($qty_verified != $qty) {
                        errorreturn('Stock quantity is not equal to the quantity in classification.');
                    }
                } else {
                    // if not batch details then manually create
                    $inventory_batch_details[] = array(
                        'rate' => ($base_price_specific / $qty),
                        'qty' => $qty,
                        'amount' => $base_price_specific
                    );
                }
            } else {

                $inventory_batch_details = null;
                $qty = 1;
            }

            $stock_record[] = array(
                'stock_id' => $stock_id, 'qty' => $qty, 'per_price' => $per_price, 'total_amount' => $stock_price_specific,
                'description' => $description, 'ledger_entries' => $ledger_entries, 'boolean_inventory' => $boolean_inventory, 'batch_details' => $inventory_batch_details
            );
        }
    }
} else {
    errorreturn("Please enter valid stock details.");
}

$credittotal = 0.00;
// at this point you merge in the common ledgers differently for both updated debit and updated credit record
$ledgerid_array = [];
$ledgeramount_array = [];

// then you push them accordingly in creditrecord or debitrecord

if (isset($postdata['ledgerrecord'])) {
    $ledgerrecord = $postdata['ledgerrecord'];
    $ledgerrecord = json_decode($ledgerrecord, true);
} else {
    $ledgerrecord = null;
}

if ($ledgerrecord !=  null and is_array($ledgerrecord)) {
    // sort ledger entries
    usort($ledgerrecord, 'compareBySequence');
    $temp_base_stock = $base_price_total; // used to calculate rows
    $temp_adjusted_stock = $base_price_total; // used to calculate rows

    $last_mainledgerhead = getLedgerSpecificLedgerhead($specific_db_conn, $ledgerrecord[0]['ledgerid'], $workspace_id, $company_id, $branch_id, $book_id);

    foreach ($ledgerrecord as $data) {

        $ledgerid = $data['ledgerid'];

        // $ledger_detail = GetBasicLedgerDetail($specific_db_conn, $ledgerid, $workspace_id, $company_id, $branch_id, $book_id, $additionaldata);

        $is_add = $data['is_add'];
        $sequence = $data['sequence'];
        $adjusted_type = $data['adjusted_type'];
        $amount = $data['total_amount'];
        $percentage = (isset($data['percentage']) and !empty($data['percentage'])) ? trim($data['percentage']) : null;

        $current_temp_main_ledgerhead = getLedgerSpecificLedgerhead($specific_db_conn, $ledgerid, $workspace_id, $company_id, $branch_id, $book_id);

        if (($last_mainledgerhead != 'Duties & Taxes' && $current_temp_main_ledgerhead == 'Duties & Taxes') || ($last_mainledgerhead == 'Duties & Taxes' && $current_temp_main_ledgerhead != 'Duties & Taxes')) {
            $temp_base_stock = $temp_adjusted_stock;
        }
        $last_mainledgerhead = $current_temp_main_ledgerhead;


        if ($adjusted_type == '0') {
            if ($percentage != null) {
                $taxamount = ((floatval($temp_base_stock) * floatval($percentage) / 100));
            } else {
                $taxamount = $amount;
            }

            if ($is_add == '1') {
                $a = array('ledgerid' => $ledgerid, 'amount' => $taxamount);
                array_push($updateddebitrecord, $a);
                $stock_final_price_total +=  $taxamount;
            } else {
                $a = array('ledgerid' => $ledgerid, 'amount' => $taxamount);
                array_push($updatedcreditrecord,  $a);
                $stock_final_price_total -=  $taxamount;
            }
        } else {

            if ($percentage != null) {
                $taxamount = ($temp_adjusted_stock) * ($percentage) / 100;
            } else {
                $taxamount = $amount;
            }

            if ($is_add == '1') {
                $a =  array('ledgerid' => $ledgerid, 'amount' => $taxamount);
                array_push($updateddebitrecord, $a);
                $stock_final_price_total +=  $taxamount;
            } else {

                $a =  array('ledgerid' => $ledgerid, 'amount' => $taxamount);
                array_push($updatedcreditrecord,  $a);
                $stock_final_price_total -=  $taxamount;
            }
        }


        if ($is_add == '1') {
            $temp_adjusted_stock += $taxamount;
        } else $temp_adjusted_stock -= $taxamount;
    }
}


if ($creditrecord != null and is_array($creditrecord)) {
    if (isset($creditrecord[0])) {
        $creditrecord[0]['amount'] = $stock_final_price_total;

        array_push($updatedcreditrecord, $creditrecord[0]);
    } else {
        if ($transactiontype == 'purchase')
            errorreturn("Purchase Ledger Not Found");
        else
            errorreturn("Party Ledger Not Found");
    }
}

if ($debitrecord != null and is_array($debitrecord)) {
    if (isset($debitrecord[0])) {
        $debitrecord[0]['amount'] = $base_price_total;

        array_push($updateddebitrecord, $debitrecord[0]);
    } else {
        errorreturn("Party Ledger Not Found");
    }
}


foreach ($updatedcreditrecord as  $item) {

    $credittotal += ($item['amount']);

    if (isset($item['param_1'])) {
        $param_1 = $item['param_1'];
    } else {
        $param_1 =  null;
    }

    $ledger_detail = GetBasicLedgerDetail($specific_db_conn, $item['ledgerid'], $workspace_id, $company_id, $branch_id, $book_id, $additionaldata);

    if ($ledger_detail[1]['ledger_main_ledgerhead'] == 'Bank Account' or $ledger_detail[1]['ledger_main_ledgerhead'] == 'Cash-in-Hand' and (key_exists('denominations', $item) or key_exists('instrument_details', $item))) {

        $additional_data = array();
        $additional_data = ['base_currency_formal_name'];

        $base_currency = GetBasicCurrencyFormalName($specific_db_conn, $workspace_id, $company_id, $branch_id, $additional_data);
        foreach ($base_currency as $currency) {
            $base_currency_formal_name = $currency['base_currency_formal_name'];
        }

        if (key_exists('instrument_details', $item)) {

            $instrument_details = $item['instrument_details'];
            validateBankInstrument($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, $instrument_details, $base_currency_formal_name, $item['ledgerid'], $book_opening_date, $book_closing_date);
        } else {
            $instrument_details = null;
        }

        if (key_exists('denominations', $item)) {
            $denominations = $item['denominations'];
            validateDenominations($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, $denominations, $base_currency_formal_name, $item['amount']);
        } else {
            $denominations = null;
        }
    } else {
        $instrument_details = null;
        $denominations = null;
    }

    $transaction_record_rows[] = array(
        'ledgerid' => $item['ledgerid'],
        'relative_amount' => - (floatval($item['amount'])),
        'ledger_main_ledgerhead' => $ledger_detail[1]['ledger_main_ledgerhead'],
        'ledger_parent_group' => $ledger_detail[0]['ledger_parent_group'],
        'amount' => abs(floatval($item['amount'])), 'balancetype' => 'cr', 'instrument_details' => $instrument_details, 'denominations' => $denominations,
        'param_1' => $param_1
    );
}

$debittotal = 0.00;
foreach ($updateddebitrecord as $item) {

    $debittotal += ($item['amount']);
    if (isset($item['param_1'])) {
        $param_1 = $item['param_1'];
    } else {
        $param_1 =  null;
    }
    $ledger_detail = GetBasicLedgerDetail($specific_db_conn, $item['ledgerid'], $workspace_id, $company_id, $branch_id, $book_id, $additionaldata);


    if ($ledger_detail[1]['ledger_main_ledgerhead'] == 'Bank Account' or $ledger_detail[1]['ledger_main_ledgerhead'] == 'Cash-in-Hand' and (key_exists('denominations', $item) or key_exists('instrument_details', $item))) {

        // call validateBankInstrument 
        $additional_data = array();
        $additional_data = ['base_currency_formal_name'];

        $base_currency = GetBasicCurrencyFormalName($specific_db_conn, $workspace_id, $company_id, $branch_id, $additional_data);
        foreach ($base_currency as $currency) {
            // print_r($currency);
            $base_currency_formal_name = $currency['base_currency_formal_name'];
        }

        if (key_exists('instrument_details', $item)) {

            $instrument_details = $item['instrument_details'];
            validateBankInstrument($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, $instrument_details, $base_currency_formal_name, $item['ledgerid'], $book_opening_date, $book_closing_date);
        } else {

            $instrument_details = null;
        }

        if (key_exists('denominations', $item)) {
            $denominations = $item['denominations'];
            validateDenominations($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, $denominations, $base_currency_formal_name, $item['amount']);
        } else {
            $denominations = null;
        }
    } else {
        $instrument_details = null;
        $denominations = null;
    }

    $transaction_record_rows[] = array(
        'ledgerid' => $item['ledgerid'],
        'relative_amount' => $item['amount'],
        'ledger_main_ledgerhead' => $ledger_detail[1]['ledger_main_ledgerhead'],
        'ledger_parent_group' => $ledger_detail[0]['ledger_parent_group'],
        'amount' => abs(floatval($item['amount'])), 'balancetype' => 'dr', 'instrument_details' => $instrument_details, 'denominations' => $denominations,
        'param_1' => $param_1
    );
}

if ($credittotal != $debittotal) {
    errorreturn('Credit total and debit total do not match.');
}

// Set the isolation level to READ COMMITTED
$specific_db_conn->exec("SET TRANSACTION ISOLATION LEVEL READ COMMITTED");

// Begin a transaction
$specific_db_conn->beginTransaction();

$allUpdatesSuccessful = true;


try {
    $result =   InsertTransactionData(
        $specific_db_conn,
        $workspace_id,
        $company_id,
        $branch_id,
        $book_id,
        $transactiontype,
        $date,
        $username,
        NULL,
        $last_modified_by,
        $narration,
        $userid,
        $reference_number,
        $dispatch_id,
        $billing_address,
        $shipping_address,
        $e_way_bill,
        $prefix_financial_year_bool,
        $financial_year_startdate,
        $transaction_numbering_system,
        $unique_id,
        $additional_transaction_prefix
    );
    $unique_id = $result['unique_id'];
    $transaction_id = $result['transaction_id'];

    //prepare query for transaction record insert
    $sql = "INSERT INTO act_transactionrecord(workspace_id,company_id,branch_id,book_id,transaction_id,ledgerid,main_ledgerhead,parent_ledgerhead,amount,balancetype,param_1,date) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)";
    $insert_into_transactionrecord =  $specific_db_conn->prepare($sql);

    foreach ($transaction_record_rows as $row1) {

        $ledgerid = $row1['ledgerid'];
        $main_ledgerhead = $row1['ledger_main_ledgerhead'];
        $parent_ledgerhead = $row1['ledger_parent_group'];
        $amount = $row1['amount'];
        $relative_amount = $row1['relative_amount'];
        $balancetype = $row1['balancetype'];
        $param_1 = $row1['param_1'];

        $insert_into_transactionrecord->execute(array($workspace_id, $company_id, $branch_id, $book_id, $transaction_id, $ledgerid, $main_ledgerhead, $parent_ledgerhead, $amount, $balancetype, $param_1, $date));

        // use update ledgerbalance here

        UpdateLedgerBalance($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, $ledgerid, $relative_amount, $date, $main_ledgerhead, $parent_ledgerhead, 1);
    }

    //add bank instrument function
    foreach ($transaction_record_rows as $row1) {
        $ledgerid = $row1['ledgerid'];
        $amount = $row1['amount'];
        $balancetype = $row1['balancetype'];
        $instrument_details = $row1['instrument_details'];
        $denominations = $row1['denominations'];
        if ($row1['instrument_details'] != null) {

            $temp_instrument_bank = AddBankInstrument($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, $instrument_details, $ledgerid, $amount, $balancetype, $transactiontype, $date, $transaction_id);
            if (!$temp_instrument_bank) {
                $specific_db_conn->rollBack();
                errorreturn('Error : Unable to save purchase transaction.');
            }

            $sql = "Update act_transactionrecord set reference_id = ? where   workspace_id = ? and company_id =? and branch_id=? and book_id =? and transaction_id= ?  and ledgerid =? ";
            $stmt = $specific_db_conn->prepare($sql);
            $stmt->execute(array($temp_instrument_bank, $workspace_id, $company_id, $branch_id, $book_id, $transaction_id, $ledgerid));
        }

        if ($row1['denominations'] != null) {
            $denominations_id = addDenominations($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, $denominations, $ledgerid, $balancetype, $transaction_id, $amount);
            if (!$denominations_id) {
                $specific_db_conn->rollBack();
                errorreturn('Error : Unable to save purchase transaction.');
            }

            $sql = "Update act_transactionrecord set reference_id = ? where   workspace_id = ? and company_id =? and branch_id=? and book_id =? and transaction_id= ? and ledgerid =? ";
            $stmt = $specific_db_conn->prepare($sql);
            $stmt->execute(array($denominations_id, $workspace_id, $company_id, $branch_id, $book_id, $transaction_id, $ledgerid));
        }
    }

    // print_r($stockrecord);die();
    // add stock transaction with update stock balances
    if ($stockrecord != null and is_array($stockrecord)) {

        foreach ($stock_record as $index => $rows) {

            $stock_id = $rows['stock_id'];

            $boolean_inventory = $rows['boolean_inventory'];
            $qty = (isset($rows['qty']) and !empty($rows['qty'])) ? trim($rows['qty']) : null;
            // $per_price = (isset($rows['per_price']) and !empty($rows['per_price'])) ? trim($rows['per_price']) : null;
            $per_price = (isset($rows['per_price']) and !empty($rows['per_price'])) ? trim($rows['per_price']) : 0;
            $total_amount = $per_price * $qty;
            $unit_id = (isset($rows['unit_id']) and !empty($rows['unit_id'])) ? trim($rows['unit_id']) : null;

            $description = (isset($rows['description']) and !empty($rows['description'])) ? trim($rows['description']) : null;
            $product_type_param1 = (isset($rows['product_type_param1']) and !empty($rows['product_type_param1'])) ? trim($rows['product_type_param1']) : null;
            $product_type_param2 = (isset($rows['product_type_param2']) and !empty($rows['product_type_param2'])) ? trim($rows['product_type_param2']) : null;
            $product_type_param3 = (isset($rows['product_type_param3']) and !empty($rows['product_type_param3'])) ? trim($rows['product_type_param3']) : null;
            //$elementToFind = $rows;

            // Get the index of the element
            //$index_of_element = array_search($rows, $stock_record);



            //stock transaction add
            $inventory_transaction_stockid = InsertStockTransactionDetails(
                $specific_db_conn,
                $workspace_id,
                $company_id,
                $branch_id,
                $book_id,
                $stock_id,
                $qty,
                $per_price,
                $total_amount,
                $unit_id,
                $description,
                $date,
                $index,
                $transactiontype,
                $transaction_id,
                $from_region,
                $product_type_param1,
                $product_type_param2,
                $product_type_param3,
                $boolean_inventory

            );

            if (!$inventory_transaction_stockid) {
                $specific_db_conn->rollBack();
                errorreturn('Error : Unable to save purchase transaction.');
            }

            $ledger_entries = $rows['ledger_entries'];
            if ($ledger_entries !=  null and is_array($ledger_entries)) {
                $ledger_entries = $rows['ledger_entries'];
                foreach ($ledger_entries as $item) {
                    $ledgerid = $item['ledgerid'];
                    $percentage = (isset($item['percentage']) and !empty($item['percentage'])) ? trim($item['percentage']) : null;
                    $is_add = $item['is_add'];
                    $total_amount = $item['total_amount'];
                    $adjusted_type = $item['adjusted_type'];
                    $sequence = $item['sequence'];

                    //stock transaction add
                    if (!InsertStockTransactionClassification($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, $inventory_transaction_stockid, $transaction_id, $ledgerid, $percentage, $total_amount, $adjusted_type, $sequence, $is_add, $index)) {
                        $specific_db_conn->rollBack();
                        errorreturn('Error : Unable to save purchase transaction.');
                    }
                }
            }

            if ($boolean_inventory == 1) {
                $inventory_batch_details = $rows['batch_details'];
            } else {
                $inventory_batch_details = null;
            }
            if ($inventory_batch_details !=  null and !empty($inventory_batch_details) and is_array($inventory_batch_details) and count($inventory_batch_details) > 0) {
                if (!InsertBatchDetails($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, $stock_id, $inventory_batch_details, $username, $transactiontype, $index, $date, $transaction_id, $default_barcode_id = null, $last_modified_by = null)) {
                    $specific_db_conn->rollBack();
                    errorreturn('Error : Unable to save purchase transaction. Error : 3');
                }
            }
        }
    }

    if ($ledgerrecord !=  null and is_array($ledgerrecord)) {

        //  $ledger_entries = $rows['ledger_entries'];
        foreach ($ledgerrecord as $item) {
            $ledgerid = $item['ledgerid'];
            $percentage = (isset($item['percentage']) and !empty($item['percentage'])) ? trim($item['percentage']) : null;
            $is_add = $item['is_add'];
            $total_amount = $item['total_amount'];
            $adjusted_type = $item['adjusted_type'];
            $sequence = $item['sequence'];

            //stock transaction add
            if (!InsertStockTransactionClassification($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, '_', $transaction_id, $ledgerid, $percentage, $total_amount, $adjusted_type, $sequence, $is_add, null)) {
                $specific_db_conn->rollBack();
                errorreturn('Error : Unable to save purchase transaction. 4');
            }
        }
    }

    if ($filesattached == null) {
        $filesattached = null;
    } else {
        $currentYear = date('Y');
        $currentMonth = date('n');
        $currentDay =  date('d');


        $directoryPathMain = "user_uploads/" .  'workspace_'  . $workspace_id . "/" . 'company_' .  $company_id . "/" . 'branch_' .  $branch_id . "/" . 'book_' .  $book_id . "/transaction_attachments/" . $currentYear . "/" . $currentMonth . "/";
        $originalFileName = $_FILES['filesattached']['name'];
        $fileTmpName = $_FILES['filesattached']["tmp_name"];
        $fileSize = $_FILES['filesattached']["size"];
        $fileType = $_FILES['filesattached']["type"];
        $fileError = $_FILES['filesattached']["error"];
        $file_extension = strtolower(pathinfo($_FILES['filesattached']['name'], PATHINFO_EXTENSION));
        $size = filesize($fileTmpName);
        // Check if it's a valid image
        $allowedTypes = [
            'image/jpeg', 'image/png', 'image/gif', 'image/heic',
            'application/pdf',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'application/vnd.ms-excel',
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        ]; // Allowed image types
        $allowed_extensions = ['jpg', 'gif', 'png', 'heic', 'jpeg', 'pdf', 'xlsx', 'xls', 'doc', 'docx'];
        $maxFileSize = 2; // Maximum file size (2MB)

        checkFileValidation($fileSize, $fileType, $file_extension, $maxFileSize, $allowedTypes, $allowed_extensions);
        awsS3UserUploadTransactionInsert($specific_db_conn, $workspace_id, $company_id, $branch_id, $book_id, $userid, $username, $size, $file_extension, $filesattached, $directoryPathMain, $transaction_id, $originalFileName);
    }


    $specific_db_conn->commit();

    $unique_id = getTransactionUniqueId($additional_transaction_prefix, $transaction_numbering_system, $unique_id, $transactiontype, $prefix_financial_year_bool, $date, $financial_year_startdate);

    successreturn(array('transaction_id' => $transaction_id, 'transaction_unique_id' =>  $unique_id, 'successmsg' => "Transaction saved successfully."));
} catch (Exception $e) {
    $specific_db_conn->rollBack();
    errorreturn("Error : " . $e->getMessage());
}
