이번포스트에서는 회원유효기간 관리와 블럭제품관리에 대한 내용을 기술할려고 한다.

목록들은 대부분 대동소이하다.

각각의 특징에 따른 필드의 차이는 있지만 대부분 프로그램밍적으로는 비슷하다

 

- 회원유효기간관리 목록

 

 

 

제품유효기간은 타이틀별로 Sort가 필요해서 페이징을 없앴다.

리스트의 타이틀을 클릭하면 항목에 따라 정렬이 된다.

스트링으로 정리를 하는 형식이라 숫자에 대한 정렬리 문제가 있었으나

인터넷을 통해 그 문제도 해결하였다.

이부분이 참 잘 안풀리던차에 구한 소스다

 

소스를 보자면

        // 숫자의 정확한 sort를 위한 StringLogicalComparer 코드

        public class StringLogicalComparer
        {

            public static int Compare(string s1, string s2)
            {

                //get rid of special cases

                if ((s1 == null) && (s2 == null)) return 0;

                else if (s1 == null) return -1;

                else if (s2 == null) return 1;

 


                if ((s1.Equals(string.Empty) && (s2.Equals(string.Empty)))) return 0;

                else if (s1.Equals(string.Empty)) return -1;

                else if (s2.Equals(string.Empty)) return -1;

 


                //WE style, special case

                bool sp1 = Char.IsLetterOrDigit(s1, 0);

                bool sp2 = Char.IsLetterOrDigit(s2, 0);

                if (sp1 && !sp2) return 1;

                if (!sp1 && sp2) return -1;

 


                int i1 = 0, i2 = 0; //current index

                int r = 0; // temp result

                while (true)
                {

                    bool c1 = Char.IsDigit(s1, i1);

                    bool c2 = Char.IsDigit(s2, i2);

                    if (!c1 && !c2)
                    {

                        bool letter1 = Char.IsLetter(s1, i1);

                        bool letter2 = Char.IsLetter(s2, i2);

                        if ((letter1 && letter2) || (!letter1 && !letter2))
                        {

                            if (letter1 && letter2)
                            {

                                r = Char.ToLower(s1[i1]).CompareTo(Char.ToLower(s2[i2]));

                            }

                            else
                            {

                                r = s1[i1].CompareTo(s2[i2]);

                            }

                            if (r != 0) return r;

                        }

                        else if (!letter1 && letter2) return -1;

                        else if (letter1 && !letter2) return 1;

                    }

                    else if (c1 && c2)
                    {

                        r = CompareNum(s1, ref i1, s2, ref i2);

                        if (r != 0) return r;

                    }

                    else if (c1)
                    {

                        return -1;

                    }

                    else if (c2)
                    {

                        return 1;

                    }

                    i1++;

                    i2++;

                    if ((i1 >= s1.Length) && (i2 >= s2.Length))
                    {

                        return 0;

                    }

                    else if (i1 >= s1.Length)
                    {

                        return -1;

                    }

                    else if (i2 >= s2.Length)
                    {

                        return -1;

                    }

                }

            }

 


            private static int CompareNum(string s1, ref int i1, string s2, ref int i2)
            {

                int nzStart1 = i1, nzStart2 = i2; // nz = non zero

                int end1 = i1, end2 = i2;

 


                ScanNumEnd(s1, i1, ref end1, ref nzStart1);

                ScanNumEnd(s2, i2, ref end2, ref nzStart2);

                int start1 = i1;

                i1 = end1 - 1;

                int start2 = i2;

                i2 = end2 - 1;

 


                int nzLength1 = end1 - nzStart1;

                int nzLength2 = end2 - nzStart2;

 


                if (nzLength1 < nzLength2) return -1;

                else if (nzLength1 > nzLength2) return 1;

 


                for (int j1 = nzStart1, j2 = nzStart2; j1 <= i1; j1++, j2++)
                {

                    int r = s1[j1].CompareTo(s2[j2]);

                    if (r != 0) return r;

                }

                // the nz parts are equal

                int length1 = end1 - start1;

                int length2 = end2 - start2;

                if (length1 == length2) return 0;

                if (length1 > length2) return -1;

                return 1;

            }

 


            //lookahead

            private static void ScanNumEnd(string s, int start, ref int end, ref int nzStart)
            {

                nzStart = start;

                end = start;

                bool countZeros = true;

                while (Char.IsDigit(s, end))
                {

                    if (countZeros && s[end].Equals('0'))
                    {

                        nzStart++;

                    }

                    else countZeros = false;

                    end++;

                    if (end >= s.Length) break;

                }

            }

 


        }

 

위의 소스를 이용하여 sort문제를 해결하였다

 

- 회원유효기간 수정

 

 

 

회원유효기간 변경은 간단하다.

사용방법은 단지 유효기간을 늘려주거나 줄여주는것이외의 기능은 없다

회원들이 시간충전을 하고 유효기간내에 다 사용을 못한 경우 임의로 유효기간을 연장시켜줄수 있는 기능을 만들어준것이다

 

- 블럭방 이용관리

 

 

블럭방이용관리는 시간충전을 한 고객이 혹시 클레임이라도 제기하면 그 사람의 히스토리를 일목정연하게 보여주기 위해서 만들어졌다.

회원검색을 하면 그 사람이 사용한 시간에 대한 정리를 해준다.

이것으로 사용시간 패턴을 구할 수 있다.

그래프로 그려볼까 하다가 특별히 쓰일일이 없을것 같아 포기했다.

 

- 블럭제품관리

 

 

블럭제품관리는 목록보기는 대부분 같이 때문에 특별히 설명할 부분이 없다

단지 여기서는 현재 사용하고 있는 목록과 필요가 없거나 파손으로 폐기처분한 목록에 대한 리스트업을 할 수 있도록 기능을 추가하였다.

 

 

- 블럭제품 등록, 폐기, 수정, 삭제

 

 

 

마지막으로 블럭제품의 등록, 폐기, 수정, 삭제에 대한 기능을 삽입해줬다.

상기 화면에서 보면 블럭제품의 등록도 최소한의 정보만 등록하도록 만들었다.

원체 복잡한것을 싫어해서...그리고 현장에서도 복잡하게 등록할 일이 없는것 같아서 최소의 정보만을 입력토록했다.

이 부분에서 정산 부분을 연동시킬까도 생각했지만 정산까지 가면 너무 솔루션이 무거워지고 그러다 보면 아무나 가져다가 무료로 사용하게 하자는 정책에서 벗어날것 같아 제외하고 추후 필요하다면 정산 솔루션을 별도록 만들어서 무료배포를 해볼까 구상중이다.

 

다음 포스트에서는 관리자 등록과 엑셀 다운로드에 대해서 정리하고 나면 기능이나 화면설명은 끝이 난다.

 

참고로 이 프로그램은 종료와 동시에 한달동안의 DB는 자동으로 백업이 되도록 구성되어 있다.

한달이 지난 것은 순차적으로 지워지고 매일매일 종료시에 데이타베이스가 백업이 된다. 물론 로컬에 백업이 된다.

다음 포스트까지 기능 설명 후에 각각 기능에서 기억에 남는 소스를 추려서 다시 소스 공개를 하고 셋업을 위해 NSIS를 사용했는데 혹시나 시간이 되면 간단하게 NSIS에 대한 설명을 하고  마무리할려고 한다.

다음 포스트를 기대해주시고

 

내용을 다른 곳으로 많이 공유해주시면 고맙겠습니다....

추천도 팍팍...

좋아요도 팍팍...

광고도 팍팍....

top


- 시간 충전과 충전목록

 

먼저 시간 충전에 대한 화면을 살펴보기로 하자

 

 

 

먼저 시간 충전을 위해서는 회원 검색을 하여야 한다.

시간충전은 기존 회원에 한하여 가능한 서비스이기 때문이다.

회원검색에서 이름을 입력한 다음 검색을 하면 해당 회원이 나타날것이다.

그러면 충전하고자 하는 회원을 선택하면 아래와 같은 화면이 나타날것이다

 

 

상기 화면에서 보면 회원번호, 이름, 연락처, 남은시간(현재 남아 있는 시간이 있는 경우 표시)이 기본적으로 나타나고 충전시간은 기본으로 20시간, 유효기간은 4개월로 지정되어 있다.

 

충전시간은 총 100시간 까지 가능하며 20시간으로 부터 20시간 단위로 추가 되도록 되어 있다.

유효기간 또한 4개월에서 2개월 단위로 추가가 되도록 설계가 되어 있다.

 

 

 

충전기록관리는 상기 이미지와 같이 회원별 기록관리와 전체기록관리로 나누어져 있다.

하단의 전체목록을 클릭하면 최종 충전한 기록들을 회원별로 보여준다.

각 회원별로 최종으로 한 1개의 기록만을 보여주는 것이다.

그러나 회원 이름으로 검색을 하면 회원에 대한 충전 기록을 모두 볼수 있다.

 

그리고 회원을 선택한다음 충전 취소버튼을 클릭하면 취소가 가능하다.

충전취소의 경우 민감한 부분이기 때문에 충전후 사용흔적이 있으면 취소가 불가능하다.

즉 충전시간보다 만은 시간이 적은경우 취소가 되지 않는다.

충전취소는 사용기록이 없어야 한다.

 

혹시 사용한 후 기존 사용건에 대한것은 현금 지불라고 취소를 하고 싶다면

블럭방이용신청에서 기존 사용건에 대한 수정을 처리한 후 남은시간과 충전시간을 같게 해주면 취소가 가능하다.

 

충전과 충전기록관리는 특별히 어렵거나 특이한것은 없다.

나중에 소스부분을 살펴볼때 추가로 설명하겠지만 개발 또한 특별히 어려운 부분은 없다.

 

오늘은 여기서 포스트를 정리하고자 한다.

다음시간에 또 ~~

top


잠시 쉬어가는 코너로 SQLite연결을 위한 전역변수 사용에 대한 부분을 살펴보자

 

먼저 참조로 System.Data.SQLite.Core를 선택해서 추가하였다.

 

using System.Data.SQLite;

 

그런 다음 전역변수로 DB연결부분을 만들었다

 

public class global_variable
        {

            //전역변수 선언부분
            private static String currentPath = Environment.CurrentDirectory; //현재 디렉토리
            private static string bDBPath = currentPath + "\\blocknori.db"; //DB명
            private static String bConnStr = String.Format("Data Source={0};password={1}", bDBPath, "비밀번호");

            private static SAdminInfo g_AInfo;

            public static string DBPath  //디비 경로 설정
            {
                get { return bDBPath; }
                set { bDBPath = value; }
            }

            public static string ConnStr  //디비 연결문자열
            {
                get { return bConnStr; }
                set { bConnStr = value; }
            }

         }

 

위와 같이 전역변수를 선언한 다음 DB연결을 진행했다.

 

DB는 설치프로그램 하단에 루트디렉토리에 존재하도록 작업을 하였다.

 

그리고 몇가지 공통되는 함수를 만들었다

그중 하나가 페이징이다

페이징에서는 가장 중요한것이 페이징 갯수를 구하는 것이다

함수를 살펴보면 아래와 같다

 

 

//페이징 갯수 구하기
     public long GetPageSize(long nTotal, long nPageNum)
        {
            double nTP;

            nTP = 0;

            try
            {
                if (nTotal == 0)
                {
                    nTP = 0;
                }
                else
                {
                    nTP = (double)(nTotal / (double)nPageNum) * (double)nPageNum;

                    if ((double)nTP % (double)nPageNum != 0)
                    {
                        nTP = (nTP / (double)nPageNum) + 1;
                    }
                    else
                    {
                        nTP = nTP / (double)nPageNum;
                    }

                }
            }
            catch { }

            return (long)nTP;
     }

 

 

메인에서 사용할때는

먼저

private long noriPageSize = 15;
        
private long chargePageCount = 0;
private long chargeCurrentPage = 1;

 

private로 변수를 선언한 다음

long TotalRecords = 총레코드수를 구한다;

noriPageCount = dbcon.GetPageSize(TotalRecords, noriPageSize);

 

이렇게 페이지 갯수를 구하면 된다.

 

다음 포스트에서도 중간 중간 특이한 함수에 대해서는 정리를 하고자 한다

 

top