UpdateBOM.java

package com.workbenchclassic;

import org.json.JSONArray;
import org.json.JSONObject;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
 * UpdateStation performs database insert depending on DB vendor (MSSQL or
 * Oracle).
 */
@Path("/updateBom")
public class UpdateBOM {
    private String[] processedMaterialNos = new String[0];
    /** Our DB service for queries (JNDI, etc.). */
    private final DBService dbService = new DBService("dsTranNJTA");

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response doUpdate(String jsonBody) {
        try {
            // 1) JSON parsen
            JSONObject json = new JSONObject(jsonBody);
            String station = json.getString("station");
            JSONArray dataArray = json.getJSONArray("data");

            // 2) DB-Vendor abfragen
            String vendor = dbService.getDatabaseProductName();
            System.out.println("Aktueller DB-Vendor: " + vendor);
            Connection conn = dbService.getConnection();
            GetMetadata metadata = new GetMetadata();
            String extPlantResponseString = metadata.getExtPlantJson(station);
            JSONObject extPlantResponse = new JSONObject(extPlantResponseString);

            String errorCode = extPlantResponse.optString("errorCode", "0");
            if (!"0".equals(errorCode)) {
                // Return an HTTP 400 or 500 with that JSON
                return Response.status(Response.Status.BAD_REQUEST).entity(extPlantResponse.toString()).build();
            }
            // 3) werknummer ermitteln

            // werkResultJson könnte z.B. so aussehen:
            // {"errorCode":"0","errorMessage":"Done","data":"[{\"werknummer\":\"ABC\"}]"}

            String werkData = extPlantResponse.optString("data", "[]");
            JSONArray werkArr = new JSONArray(werkData);

            String WERK_NR = null;
            String COMPANY_NO = null;
            String CLIENT_NO = null;
            if (werkArr.length() > 0) {
                JSONObject row = werkArr.getJSONObject(0);
                WERK_NR = row.optString("ext_company_nr", null);
                COMPANY_NO = row.optString("werk_nr", null);
                CLIENT_NO = row.optString("client_nr", null);
            }

            boolean isMSSQL = "Microsoft SQL Server".equals(vendor);
            boolean isOracle = "Oracle".equals(vendor);

            // 4) ZUERST den tran_idocstatus-Eintrag anlegen
            if (isMSSQL) {
                String insertIdocstatusMSSQL = "INSERT INTO xtran.tran_idocstatus (ID, DATE_CREATION, ewstatus, errorcode, content_type, source) VALUES ( (NEXT VALUE FOR xtran.seq_tranidocstatus), getdate(), 1, 0, 1, 0)";
                dbService.dbConnect(insertIdocstatusMSSQL);
            } else if (isOracle) {
                String insertIdocstatusOracle = "INSERT INTO xtran.tran_idocstatus (ID, DATE_CREATION, ewstatus, errorcode, content_type, source) VALUES ( tran.seq_tranidocstatus.nextval, sysdate, 1, 0, 1, 0)";
                dbService.dbConnect(insertIdocstatusOracle);
            } else {
                System.out.println("DB-Vendor nicht implementiert: " + vendor);
            }

            // 5) Für JEDES Element in "data" => Insert in material

            conn.setAutoCommit(false); // Transaktion starten

            try {
                for (int i = 0; i < dataArray.length(); i++) {
                    JSONObject obj = dataArray.getJSONObject(i);
                    insertBomHead(conn, obj, COMPANY_NO, WERK_NR, CLIENT_NO, isMSSQL, isOracle);
                    insertBomItem(conn, obj, COMPANY_NO, WERK_NR, CLIENT_NO, isMSSQL, isOracle);
                }
                conn.commit(); // Transaktion bestätigen
            } catch (SQLException e) {
                conn.rollback(); // Transaktion rückgängig machen
                throw e; // Weiterleitung des Fehlers
            } finally {
                conn.setAutoCommit(true); // Auto-Commit wieder aktivieren
                conn.close(); // Verbindung schließen
            }

            // 6) Erfolgreich fertig
            JSONObject response = new JSONObject();
            response.put("status", "ok");
            response.put("message", "Daten wurden erfolgreich verarbeitet.");
            return Response.ok(response.toString()).build();

        } catch (Exception e) {
            e.printStackTrace();
            JSONObject error = new JSONObject();
            error.put("status", "error");
            error.put("message", e.getMessage());
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error.toString()).build();
        }
    }

    private void insertBomHead(Connection conn, JSONObject obj, String werknummer, String WERK_NR, String CLIENT_NO,
            boolean isMSSQL, boolean isOracle)
            throws SQLException {
        String sql;

        String materialNo = obj.optString("MATERIAL_NO");
        if (Arrays.asList(processedMaterialNos).contains(materialNo)) {
            System.out.println("MATERIAL_NO '" + materialNo + "' wurde bereits verarbeitet. Überspringe INSERT.");
            return; // Überspringen des INSERTs
        }
        if (isMSSQL) {

            sql = "INSERT INTO xtran.tran_BOM_head (BOM_ID, MATERIAL_NO, BOM_STATUS, BOM_VERSION_ERP, BOM_INDEX, BOM_INFO, PLANT_NO, CLIENT_NO, COMPANY_NO, BAREBOARD_NO, SOURCE, IDOC_ID) "
                    +
                    "VALUES (NEXT VALUE FOR xtran.SEQ_TRANBOMHEAD, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, (SELECT MAX(id) FROM xtran.tran_idocstatus))";
            System.out.println("Insert: " + sql);
        } else if (isOracle) {
            sql = "INSERT INTO xtran.tran_BOM_head (BOM_ID, MATERIAL_NO, BOM_STATUS, BOM_VERSION_ERP, BOM_INDEX, BOM_INFO, PLANT_NO, CLIENT_NO, COMPANY_NO, BAREBOARD_NO, SOURCE, IDOC_ID) "
                    +
                    "VALUES (xtran.SEQ_TRANBOMHEAD.nextval, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, (SELECT MAX(id) FROM xtran.tran_idocstatus))";
        } else {
            throw new SQLException("DB-Vendor nicht implementiert");
        }

        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            String bomVersionErp = obj.optString("BOM_VERSION_ERP", "");
            String bomIndex = obj.optString("BOM_INDEX", "");
            String bomInfo = obj.optString("BOM_INFO", "");
            String clientNo = obj.optString("CLIENT_NO", CLIENT_NO);
            String companyNo = obj.optString("COMPANY_NO", WERK_NR);
            String bareboardNo = obj.optString("BAREBOARD_NO", "");
            String source2 = obj.optString("SOURCE", "" + 0);
            int source = Integer.parseInt(source2);
            ps.setString(1, materialNo);
            ps.setString(2, "S");
            ps.setString(3, bomVersionErp);
            ps.setString(4, bomIndex);
            ps.setString(5, bomInfo);
            ps.setString(6, werknummer);
            ps.setString(7, clientNo);
            ps.setString(8, companyNo);
            ps.setString(9, bareboardNo);
            ps.setInt(10, source);

            System.out.println("Insert: " + sql);
            System.out.println("Parameters:");
            System.out.println("  1: MATERIAL_NO = " + materialNo);
            System.out.println("  2: BOM_STATUS = S");
            System.out.println("  3: BOM_VERSION_ERP = " + bomVersionErp);
            System.out.println("  4: BOM_INDEX = " + bomIndex);
            System.out.println("  5: BOM_INFO = " + bomInfo);
            System.out.println("  6: PLANT_NO = " + werknummer);
            System.out.println("  7: CLIENT_NO = " + clientNo);
            System.out.println("  8: COMPANY_NO = " + companyNo);
            System.out.println("  9: BAREBOARD_NO = " + bareboardNo);
            System.out.println("  10: SOURCE = " + source);
            ps.executeUpdate();
            processedMaterialNos = Arrays.copyOf(processedMaterialNos, processedMaterialNos.length + 1);
            processedMaterialNos[processedMaterialNos.length - 1] = materialNo;
        }
    }

    private void insertBomItem(Connection conn, JSONObject obj, String werknummer, String WERK_NR, String CLIENT_NO,
            boolean isMSSQL, boolean isOracle)
            throws SQLException {
        String sql;
        if (isMSSQL) {
            sql = "INSERT INTO xtran.tran_BOM_item (BOM_ID, COMPONENT_NO, COMP_NAME, POS_TYPE, ALTERNATIVE, " +
                    "ALTERNATIVE_PROPABILITY, WORKSTEP_ERP, PROCESS_GROUP, LAYER, QTY, UNIT, SETUP_FLAG, STATUS, INFO_TXT, PRODUCT, ERP_POS_NO) "
                    +
                    "VALUES ((SELECT MAX(BOM_ID) FROM xtran.tran_BOM_head), ?, ?, ?, ?, '0', ?, ?, ?, ?, ?, ?, 0, ?, ?, ?)";
        } else if (isOracle) {
            sql = "INSERT INTO tran.tran_BOM_item (BOM_ID, COMPONENT_NO, COMP_NAME, POS_TYPE, ALTERNATIVE, " +
                    "ALTERNATIVE_PROPABILITY, WORKSTEP_ERP, PROCESS_GROUP, LAYER, QTY, UNIT, SETUP_FLAG, STATUS, INFO_TXT, PRODUCT, ERP_POS_NO) "
                    +
                    "VALUES ((SELECT MAX(BOM_ID) FROM tran.tran_BOM_head), ?, ?, ?, ?, '0', ?, ?, ?, ?, ?, ?, 0, ?, ?, ?)";
        } else {
            throw new SQLException("DB-Vendor nicht implementiert");
        }

        System.out.println("Insert BOM: " + sql);
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setString(1, obj.optString("COMPONENT_NO")); // COMPONENT_NO
            ps.setString(2, obj.optString("COMP_NAME")); // COMP_NAME
            ps.setInt(3, obj.optInt("POS_TYPE")); // POS_TYPE
            ps.setString(4, obj.optString("ALTERNATIVE", "")); // ALTERNATIVE
            ps.setString(5, obj.optString("WS_ERP", "")); // ALTERNATIVE
            ps.setString(6, obj.optString("PROCESS_GROUP", "")); // PROCESS_GROUP
            ps.setString(7, obj.optString("LAYER", "")); // LAYER
            ps.setInt(8, obj.optInt("QTY", 0)); // QTY

            String unit = obj.optString("UNIT"); // UNIT
            try {
                Integer.parseInt(unit);
                ps.setString(9, unit); // Wenn es ein Integer ist, direkt einfügen
            } catch (NumberFormatException e) {
                String unitLower = unit.toLowerCase();
                HashMap<String, String> unitMapping = new HashMap<>();
                unitMapping.put("mm", "11000");
                unitMapping.put("zoll", "11001");
                unitMapping.put("stk", "11002");
                unitMapping.put("pcs", "11002");
                unitMapping.put("qty", "11002");
                unitMapping.put("cm", "11003");
                unitMapping.put("m", "11004");
                unitMapping.put("g", "11005");
                unitMapping.put("kg", "11006");
                unitMapping.put("ml", "11007");
                unitMapping.put("l", "11008");

                String mappedUnit = unitMapping.get(unitLower);
                if (mappedUnit != null) {
                    ps.setString(9, mappedUnit); // Mapping-Wert verwenden
                } else {
                    ps.setString(9, unit); // Originalwert verwenden, wenn kein Mapping gefunden wurde
                }
            }

            ps.setString(10, obj.optString("SETUP_FLAG", "")); // SETUP_FLAG
            ps.setString(11, obj.optString("INFO_TXT", "")); // INFO_TXT (leer)
            ps.setString(12, obj.optString("PRODUKT")); // PRODUCT
            ps.setString(13, obj.optString("ERP_POS_NO", "")); // ERP_POS_NO

            ps.executeUpdate();
        }
    }
}