erp 도전

장고 여행사 재고관리 도전 1 (4/14-4/20)

나도초딩 2023. 4. 21.

지금까지 꾸역 꾸역 답보고 문제 푸는 것처럼, 실습은 했지만 효과가 너무나 미약했기에,

 

가장 작은 프로젝트라도 만들어 보기로 했다.

결론부터 말하자면, 정말 이게 답이였다.

 

1일차

4/14 : 기존 실습한 파일을 변형해서 만들어보기로.

뭔가 만들려고 하니까, 그냥 가슴이.... 답답.....해지면서, 소화불량.... 허억...

사실 블로그야 연습용이지, 많고 좋은 블로그 속에, 장고로 블로그 만들어서 어디 써먹겠나.

 

그럴듯한 인벤토리, CRM, ERP 디자인을 찾아 헤매다 몇 시간 지나갔다. 이게 뭐람. -_-;;

 

이런 짓 하지 말고, 디자인 빼고,

이것부터 해보기로 했다.

  • 2023-5-1 부터 2020-8-31 까지,
  • 수, 토 주 2회 패턴으로 뜨는 동남아 항공편이 있다.
  • 이 정보를 일괄 입력하고, 수정할 수 있는 페이지를 만들자.

 

 

 

와.... 이게 이렇게 어려울 줄이야...

하.......................... 

알아야할게 어마어마했다.

와 ... 정말 깜짝 놀랬다.

와 이게 거의 다네.

 

이거 하나 하면서, 와.... 아리까리하고, 실습할 때 잘 몰랐던 것들의 8-90% 를 알게됐다.

 

1. models.py

모델부터 만들어야지. Category 와 Post , 추가하면 Tag 정도였는데, 이걸 생각해서

BasicCode 와 TourItem 이란 모델을 만들었다.

BasicCode : 상품코드 6자리, 상품명, 상품 설명, 이미지 필드, 파일 필드가 들어간다.

1) BasicCode

class BasicCode(models.Model):
    basic_code = models.CharField('기초코드',max_length=6, unique=True, help_text="예)ATP101")
    title = models.CharField('기초 상품 제목', max_length=80, help_text="방콕/파타야 빠빠빠 상품")
    hook_text = models.CharField('상품설명',max_length=120, blank=True)
    # content = models.TextField()
    content = MarkdownxField()
    head_image = models.ImageField(upload_to='tour/images/%Y/%m/%d/', blank=True)
    file_upload = models.FileField(upload_to='tour/files/%Y/%m/%d/', blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    author = models.ForeignKey(User, null=True,blank=True, on_delete=models.SET_NULL)
    # 카테고리 지워지면, 연결된 Tour까지 삭제되면 안됨 -> models.SET_NULL
    category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.SET_NULL)
   
    tags = models.ManyToManyField(Tag, blank=True)


    def __str__(self):
        return f'{self.basic_code}'

    def get_absolute_url(self):
        return f'/tour/{self.pk}/'

    def get_file_name(self):
        return os.path.basename(self.file_upload.name)

  
    def get_file_ext(self):
        return self.get_file_name().split('.')[-1]
   

    def get_content_markdown(self):
        return markdown(self.content)

TourItem

class TourItem(models.Model):
    basic_code = models.ForeignKey(BasicCode, null=True, blank=True, on_delete=models.SET_NULL, related_name = 'tour_item')
    air_code = models.CharField(max_length=2)
    suffix_code = models.CharField(max_length=2, blank=True)
    #item_code, item_no 구현..? zfill 이용. 나중에
    title = models.CharField(max_length=50, blank=True)
    content = models.CharField(max_length=50, blank=True) # 일정표 상세
    etc = models.CharField(max_length=50, blank=True)
    airline = models.CharField(max_length=20, blank=True)
    price = models.IntegerField("숫자", default = 0, help_text="미입력시 0. 문의")
    author = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
    air_sync = models.BooleanField(default = True, blank=True, null=True)
    d_city1 = models.CharField(max_length=3, blank=True)
    d_city2 = models.CharField(max_length=3, blank=True)
    d_date1 = models.DateField(default=date(2000,1,1))

    d_daychange = models.IntegerField(default=1)
    stay = models.IntegerField(default=5)
    r_daychange = models.IntegerField(default=1)
    d_time1 = models.TimeField(default=time(19,00))
    d_time2 = models.TimeField(default=time(23,30))
    r_city1 = models.CharField(max_length=3, blank=True)
    r_city2 = models.CharField(max_length=3, blank=True)
    r_time1 = models.TimeField(default=time(23, 30))
    r_time2 = models.TimeField(default=time(6, 00))

    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f'{self.title}'
    def item_code(self):
        day_code = self.d_date1.strftime("%Y%m%d")
        basic_code = self.basic_code.basic_code
        air_code = self.air_code
        code_suffix = self.suffix_code
        full_code = (day_code+basic_code+air_code+code_suffix)
        return full_code

    def 요일(self):
        return f'{date.strftime(self.d_date1, "%a")}'
    @property
    def r_date1(self):
        return self.d_date1 + timedelta(self.stay -2 )
        # f'{}' 스트링을 안쓰면, date 객체로 리턴.->템플릿 필터에서 format 사용가능.

    def r_date2(self):
        return self.d_date1 + timedelta(self.stay - 2 + self.r_daychange)

최소한 필수 기능만 구현하고, 나중에 필드 추가하려고 하는데, 이것만 해도 엄청 많았다.

 

1. 개발 실무에서는 fk 를 거의 안쓴다고 하는데, 아 몰라. 변수 만들기 싫으니 이대로 할래.

2. 엑셀처럼 생각하면, 정말 쉽게 생각했는데.... 와 대박. 

블로그 예제에서 크게 중요하지 않았던, 날짜 필드였는데,

 

  • DB 필드
  • settings : UTC , timezone 설정
  • admin 템플릿에서 보이기. ( admin 커스텀 )
  • 실제 웹 템플릿에서 표현과 폼으로 받아서 처리
  • view 에서 날짜객체<->스트링, 저장, 연산(for 문 리스트, 객체 등)
  • crud 구현. ( 제약조건, fk 데이터 함께 저장, 기존 날짜+코드 중복이 있을 시, 입력 거부 메세지. 제외하고, 신규 입력)
  • 기존 날짜와 코드가 중복인 것 체크하기. 어떻게? 날짜 + fk인 기초코드.basic_code + 항공코드 + 구분코드를 합쳐서 빼주는 메서드 만들기.
  • 와.... 이건 블로그에 정리한다는 것 자체가 어렵겠어. 흐름이 끊기는 것도 그렇고.... 

와.... 이건 뭐지.

view 는 더 복잡한데....

이후, 일정표 , 예약관리, 정산

이렇게 만들면 되는데 .... 흠. 이거 잘 만들면서 연습되고 하면, 훨씬 수월하게 만들 것 같다.

 

그리고 나면, 역시나 프론트 공부를 한참 해야게띠? ㅠ 올해까진 할 수 있을까? ^^

 

이번 주, 예약 조회 및 상품 추가, 수정까지 완료.

 

이후, 일정표 구현, 예약관리 등을 구현하려고 한다... 와 둘다 엄청 큰 작업들이긴 하겠다.

 

일정표가 3일, 5일, 7일 짜리 인 경우, 어떻게 구현해야하는지 떠오르지가 않는다.

날짜별 아이템마다, 수십개의 일정 필드가 필요할텐데... 흠. 이거 어케 구현해야하지? 다른건 그냥 노가다지만,

일자마다, 필드를 추가하는 건 아닌 것 같고. 5일짜리면, <div container= 일정-1 ,2,3,4,5 가 생성되야할까?  이건 아닌 것 같은데...일자를 수정하면 일정표가 문제되니까. 아 몰랑... 어케해야되냐궁

 

댓글