Windows/MFC

MFC & Oracle

aucd29 2013. 10. 2. 17:58
[code]unsigned int __cdecl CardThread(LPVOID /* lpData */)
{

    // 재진입을 막기

    static bool flagRun = false;

    if (flagRun) return 0;

    flagRun = true;



    CDatabase dbRemote;                     // 원격 DB

    CDatabase dbLocal;                     // 로컬 DB

    CRecordset cSetRemote(&dbRemote);     // 원격 SET

    CRecordset cSetLocal(&dbLocal);         // 로컬 SET

    CString cust_type, cust_code, car_no, card_no, junpyo_qty, cust_name, owner_name, sale_type, MDateTime;

    CString strMyMDateTime;                                         // 보낼 기준 시각





    // STEP 1. 원격지 데이타 베이스와 접속

    try {

        dbRemote.OpenEx("DSN=ORACLE; UID=system; PWD=mirae4064;", CDatabase::noOdbcDialog);

        dbRemote.SetQueryTimeout(180);

    }

    catch(CDBException * e)

    {

        AfxMessageBox("카드 공유 기능 동작 불가\n" + e->m_strError);

        e->Delete();

        return 0;

    }



    // STEP 2. 친구 충전소 코드리스트 파악

    CString strCode[100];                 // 충전소 코드 저장

    CString strMDateTime[100];             // 갱신 일시

    int cntCode = 0;                        // 충전소 코드 수

    CString strSQL, str;



    // 나의 코드가 읽어와야 할 충전소 코드 쿼리

    strSQL = "SELECT codeyour, mdatetime FROM fscode WHERE codeme = '";

    strSQL += theApp.m_ServiceStation.StationCode;

    strSQL += "'";

    // 열기

    try {

        cSetRemote.Open(CRecordset::forwardOnly, strSQL);

    }

    catch(CDBException * e) {

        e->Delete();

        goto _exit;

    }

    // 읽기

    short nIndex;

    while (!cSetRemote.IsEOF()) {

        nIndex = 0;

        try {        

            cSetRemote.GetFieldValue(nIndex ++, str);     // 충전소 코드

            strCode[cntCode] = str;

            cSetRemote.GetFieldValue(nIndex ++, str);     // 갱신 일시

            strMDateTime[cntCode] = str;

            if (strMDateTime[cntCode].IsEmpty()) strMDateTime[cntCode] = "0";

            cSetRemote.MoveNext();

        }

        catch(CDBException * e) {

            e->Delete();

            goto _exit;

        }

        // 충전소 코드 수 증가

        cntCode ++;

    }

    cSetRemote.Close();



    // 읽어올 코드가 없으면 종료

    if (cntCode == 0) goto _exit;



    // STEP 3. 로컬 데이타 베이스 열기

    try {

        dbLocal.OpenEx("DSN=NEWPOSPRO; UID=SA; PWD=mirae2lg;", CDatabase::noOdbcDialog);

        // 쿼리 타임아웃을 3분

        // 1분으로 해두었더니 실패한다

        dbLocal.SetQueryTimeout(180);

        // POSPRO디비를 선택한다

        dbLocal.ExecuteSQL("USE POSPRO");

    }

    catch(CDBException * e)

    {

        e->Delete();

        goto _exit;

    }



    // STEP 4. 친구 충전소 카드 자료에서 갱신 일시 이후 발생한 카드를 읽어오면서, mechul_info에 저장하고, SC에 전송한다.

    int i;

    for (i = 0; i < cntCode; i ++) {

        // 친구 충전소의 신규 데이타 읽어오는 쿼리

        strSQL = "SELECT cust_type, cust_code, car_no, card_no, junpyo_qty, cust_name, owner_name, sale_type, MDateTime ";

        strSQL += "FROM FS";

        strSQL += strCode[i];

        strSQL += " WHERE MDateTime > '";

        strSQL += strMDateTime[i];

        strSQL += "'";



        // 열어보자

        try {



            cSetRemote.Open(CRecordset::forwardOnly, strSQL);

        }

        catch(CDBException * e) {

            MessageBox(NULL, e->m_strError, "카드 쓰레드 디버그 메시지1", MB_OK);

            e->Delete();

            goto _exit;

        }



        // 아이템 카운트

        int nCountOfRecord = 0;



        // 전체 데이터에 대하여

        short nIndex;

        CString NewMDateTime;

        while(!cSetRemote.IsEOF()) {

            nCountOfRecord ++;



            // 각 필드를 읽어온다

            nIndex = 0;

            cSetRemote.GetFieldValue(nIndex ++, cust_type);

            cSetRemote.GetFieldValue(nIndex ++, cust_code);

            cSetRemote.GetFieldValue(nIndex ++, car_no);

            car_no.TrimRight();

            cSetRemote.GetFieldValue(nIndex ++, card_no);

            cSetRemote.GetFieldValue(nIndex ++, junpyo_qty);

            cSetRemote.GetFieldValue(nIndex ++, cust_name);

            cSetRemote.GetFieldValue(nIndex ++, owner_name);

            cSetRemote.GetFieldValue(nIndex ++, sale_type);

            cSetRemote.GetFieldValue(nIndex ++, MDateTime);



            if (NewMDateTime < MDateTime) NewMDateTime = MDateTime;

            cSetRemote.MoveNext();



            // 읽어온 것을 Mechul_Info에 적용

            // Mechul_Info에 있는 것을 삭제

            strSQL.Format("DELETE FROM mechul_info WHERE car_no = '%s' AND SubString(card_no, 15, 1) = '%c' ", car_no, card_no[14]);

            try {

                dbLocal.ExecuteSQL(strSQL);

            }

            catch(CDBException * e)

            {

                MessageBox(NULL, e->m_strError, "카드 쓰레드 디버그 메시지2", MB_OK);

                e->Delete();

                goto _exit;

            }



            // Mechul_info에 저장

            strSQL.Format(

                "INSERT INTO mechul_info ( "

                    "station_code, "

                    "cust_type,"

                    "cust_code, "

                    "car_no,"

                    "card_no, "



                    "junpyo_qty, "

                    "cust_name, "

                    "owner_name, "

                    "sale_type, "

                    "car_count, "



                    "car_id"

                ") VALUES ("

                    "'%s',"

                    "'%s',"

                    "'%4.4s',"

                    "'%12.12s',"

                    "'%16.16s',"



                    "%s,"

                    "'%s',"

                    "'%s',"

                    "'%s',"

                    "'%c',"



                    "'%c')"

                

                    ,theApp.m_ServiceStation.StationCode

                    ,cust_type

                    ,cust_code

                    ,car_no

                    ,card_no



                    ,junpyo_qty

                    ,cust_name

                    ,owner_name

                    ,sale_type

                    ,card_no[15]



                    ,card_no[14]);



            try {

                dbLocal.ExecuteSQL(strSQL);

            }

            catch(CDBException * e)

            {

                MessageBox(NULL, e->m_strError + "\n" + strSQL, "카드 쓰레드 디버그 메시지3", MB_OK);

                e->Delete();

                goto _exit;

            }



            // 삭제 명령을 메모리에 저장한다

            CardThreadMemory.strDEL.Format("\x02" "DEL%12.12s%c", car_no, card_no[14]);

            // 삭제 명령을 SC 쓰레드에서 쏘도록 플래그를 변경한다

            CardThreadMemory.Flag.threadDEL = !CardThreadMemory.Flag.threadDEL;

            // SC가 삭제를 완료하여 SC의 플래그가 카드 쓰레드의 플래그와 같아질때까지 기다린다

            while(CardThreadMemory.Flag.threadDEL != CardThreadMemory.Flag.scDEL) Sleep(100);



            // 삭제 데이타인 경우엔 SC에게 전송하지 않고 그외는 전송한다

            if (card_no < "DELETE_RECORD_") {

                // 거래처 명칭이 수신된 경우, 수신된 명칭을 기억한다

                theApp.m_CustCode2Name[atoi(cust_code)] = cust_name;



                // SC에게 전송

                CardThreadMemory.strCSD.Format(

                    "\x02"

                    "CSD"

                    "%16.16s"         // 카드 번호, 아스키 '0'부터 '9'까지 범위만 사용

                    "%4.4s"             // 거래처 코드 0~9999까지, 업체 코드의 한계는 10000개로 제한함

                    "%1.1s"             // 거래 종류, '1'부터 '7'까지, CUST_TYPE_NOTUSED 참조할것

                    "%s"                // 0=기업, 1=개인

                    "%02d"             // 전표량

                    "%-12.12s"         // 차량 번호

                    "%c"                // ID

                    "%c"                // 회차

                    "%-10.10s"         // 사용자 성명, KS5601완성형 코드



                    , card_no         // 카드 번호, 아스키 '0'부터 '9'까지 범위만 사용

                    , cust_code         // 거래처 코드 0~9999까지, 업체 코드의 한계는 10000개로 제한함

                    , sale_type         //

                    , cust_type         // 0=기업, 1=개인

                    , atoi(junpyo_qty) % 100

                    , car_no            // 차량번호

                    , card_no[14]     // ID

                    , card_no[15]     // 회차

                    , owner_name        // 사용자 성명, KS5601완성형 코드

                );



                // SC쓰레드가 카드 데이타 전송을 하도록 플래그 세트

                CardThreadMemory.Flag.threadCSD = !CardThreadMemory.Flag.threadCSD;



                // 전송 명령이 수행되어서 SC에서 말소될 때까지 기다린다

                while(CardThreadMemory.Flag.threadCSD != CardThreadMemory.Flag.scCSD) Sleep(100);

            }        

        }

        cSetRemote.Close();



        // 조치한 레코드가 있는 경우에만 조치한 갱신 시간을 저장

        if (nCountOfRecord > 0) {

            // 친구 테이블 업데이트가 끝났음을 저장

            strSQL = "UPDATE FSCODE SET mdatetime = '";

            strSQL += NewMDateTime;

            strSQL += "' ";

            strSQL += "WHERE codeme = '";

            strSQL += theApp.m_ServiceStation.StationCode;

            strSQL += "' AND ";

            strSQL += "codeyour = '";

            strSQL += strCode[i];

            strSQL += "';";

            dbRemote.ExecuteSQL(strSQL);

        }

    }



    // STEP 5. 내 자료를 보내기

    // STEP 5-1, 내 자료를 보낼 기준 읽기

    strSQL = "SELECT MDateTime FROM FS";

    strSQL += theApp.m_ServiceStation.StationCode;

    strSQL += " ORDER BY MDateTime DESC";

    try {

        cSetRemote.Open(CRecordset::forwardOnly, strSQL);         // 열고

        if (!cSetRemote.IsEOF()) {                                 // 없으면 읽지 않아야 에러가 안남

            cSetRemote.GetFieldValue((short) 0, strMyMDateTime);    // 읽고

        }

        cSetRemote.Close();             // 닫는다

    }

    catch(CDBException * e) {         // 에러나면

        AfxMessageBox("카드정보 송신 실패\n" + e->m_strError);     // 에러 메시지를 표시하고

        e->Delete();

        goto _exit;

    }



    strSQL =

        "SELECT cust_type, cust_code, car_no, card_no, junpyo_qty, cust_name, owner_name, sale_type, MDateTime "

        "FROM Mechul_Info "

        "WHERE MDateTime > '" + strMyMDateTime + "' AND cust_code > '0000' "

        "ORDER BY MDateTime ";         // 제일 과거 것부터 순서대로 작업해야 작업하다 꺼져도 되지...

    try {

        cSetLocal.Open(CRecordset::forwardOnly, strSQL);

        while(!cSetLocal.IsEOF()) {     // 끝까지 원격 db에 적용한다

            // 로컬의 데이타를 읽어들인다

            nIndex = 0;

            cSetLocal.GetFieldValue(nIndex ++, cust_type);

            cSetLocal.GetFieldValue(nIndex ++, cust_code);

            cSetLocal.GetFieldValue(nIndex ++, car_no);

            cSetLocal.GetFieldValue(nIndex ++, card_no);

            cSetLocal.GetFieldValue(nIndex ++, junpyo_qty);

            cSetLocal.GetFieldValue(nIndex ++, cust_name);

            cSetLocal.GetFieldValue(nIndex ++, owner_name);

            cSetLocal.GetFieldValue(nIndex ++, sale_type);

            cSetLocal.GetFieldValue(nIndex ++, MDateTime);

            cSetLocal.MoveNext();



            // 원격지에서 데이타 삭제

            strSQL = "DELETE FROM FS";

            strSQL += theApp.m_ServiceStation.StationCode;

            strSQL += " WHERE car_no = '";

            strSQL += car_no;

            strSQL += "' AND SubStr(card_no, 15, 1) = '"; // MS = SUBSTRING, ORACLE = SUBSTR

            strSQL += card_no[14];

            strSQL += "' ;";

            dbRemote.ExecuteSQL(strSQL);



            // 새로운 데이타 삽입

            strSQL = "INSERT INTO FS";

            strSQL += theApp.m_ServiceStation.StationCode;

            strSQL += "(cust_type, cust_code, car_no, card_no, junpyo_qty, cust_name, owner_name, sale_type, MDateTime)";

            strSQL += "VALUES (";

            strSQL += "'" + cust_type + "',";

            strSQL += "'" + cust_code + "',";

            strSQL += "'" + car_no + "',";

            strSQL += "'" + card_no + "',";

            strSQL += junpyo_qty + ",";

            strSQL += "'" + cust_name + "',";

            strSQL += "'" + owner_name + "',";

            strSQL += "'" + sale_type + "',";

            strSQL += "'" + MDateTime + "');";

            dbRemote.ExecuteSQL(strSQL);



            // 롤백 되지 않도록 커밋

            dbRemote.ExecuteSQL("COMMIT;");

        }

    }

    catch (CDBException * e) {

        AfxMessageBox("카드 자료를 서버에 전송하는 중에\n" + e->m_strError);

        e->Delete();

        dbRemote.Close();

    }



_exit:

    // 재진입 트기

    flagRun = false;



    return 0;

}
[/code]