[014] 플러터 (Flutter) 실전어플제작 - 쇼핑몰 앱 제작(로직구성6 - 주문 데이터 파이어스토어에 삽입하기)

2024. 2. 12. 14:50모바일어플개발/Flutter 실전어플 개발

반응형

안녕하세요~ totally 개발자입니다.

 

오늘은 결제시작 부분에서 결제 버튼을 눌렀을 때, 주문하고자 하는 제품들을 파이어스토어에 담아보도록 하겠습니다.

 

Step 1: 파이어스토어에 접속하셔서 orders 컬렉션을 생성해주시기 바랍니다. 다음을 눌러서 임의로 문서(document) 하나 추가해주시면 됩니다.

 

Step 2: lib > item_checkout_page.dart에서 checkoutContainer 부분에 혹시 height 지정을 안하신 경우에 height: 130 정도로 설정해주시기 바랍니다.

 

 

Step 3: lib > models > order.dart 파일을 열어서 아래처럼 수정해줍니다. class Order로 하면 다른 dart 파일과 겹치는 내용들이 있는 것 같아 ProductOrder로 변경하여 구분하였습니다.

 

class ProductOrder {
  String? orderNo;
  int? productNo;
  String? orderDate;
  String? buyerName;
  String? buyerEmail;
  String? buyerPhone;
  String? receiverName;
  String? receiverPhone;
  String? receiverZip;
  String? receiverAddress1;
  String? receiverAddress2;
  String? userPwd;
  String? paymentMethod;
  int? quantity;
  double? unitPrice;
  double? totalPrice;
  String? paymentStatus;
  String? deliveryStatus;

  ProductOrder({
    this.orderNo,
    this.productNo,
    this.orderDate,
    this.buyerName,
    this.buyerEmail,
    this.buyerPhone,
    this.receiverName,
    this.receiverPhone,
    this.receiverZip,
    this.receiverAddress1,
    this.receiverAddress2,
    this.userPwd,
    this.paymentMethod,
    this.quantity,
    this.unitPrice,
    this.totalPrice,
    this.paymentStatus,
    this.deliveryStatus,
  });

  ProductOrder.fromJson(Map<String, dynamic> json) {
    orderNo = json['orderNo'];
    productNo = json['productNo'];
    orderDate = json['orderDate'];
    buyerName = json['buyerName'];
    buyerEmail = json['buyerEmail'];
    buyerPhone = json['buyerPhone'];
    receiverName = json['receiverName'];
    receiverPhone = json['receiverPhone'];
    receiverZip = json['receiverZip'];
    receiverAddress1 = json['receiverAddress1'];
    receiverAddress2 = json['receiverAddress2'];
    userPwd = json['userPwd'];
    paymentMethod = json['paymentMethod'];
    quantity = json['quantity'];
    unitPrice = double.parse(json['unitPrice']);
    totalPrice = double.parse(json['totalPrice']);
    paymentStatus = json['paymentStatus'];
    deliveryStatus = json['deliveryStatus'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = {};
    data['orderNo'] = orderNo;
    data['productNo'] = productNo;
    data['orderDate'] = orderDate;
    data['buyerName'] = buyerName;
    data['buyerEmail'] = buyerEmail;
    data['buyerPhone'] = buyerPhone;
    data['receiverName'] = receiverName;
    data['receiverPhone'] = receiverPhone;
    data['receiverZip'] = receiverZip;
    data['receiverAddress1'] = receiverAddress1;
    data['receiverAddress2'] = receiverAddress2;
    data['userPwd'] = userPwd;
    data['paymentMethod'] = paymentMethod;
    data['quantity'] = quantity;
    data['unitPrice'] = unitPrice;
    data['totalPrice'] = totalPrice;
    data['paymentStatus'] = paymentStatus;
    data['deliveryStatus'] = deliveryStatus;
    return data;
  }
}

 

 

 

Step 4: lib > enums > delivery_status.dart 파일을 아래처럼 업데이트해줍니다.

 

enum DeliveryStatus {
  //! 상태 열거
  waiting('waiting', '배송대기'),
  delivering('delivering', '배송중'),
  delivered('delivered', '배송완료');

  //! 생성자
  const DeliveryStatus(this.status, this.statusName);

  final String status;
  final String statusName;

  //! 상태 이름 변환
  factory DeliveryStatus.getStatusName(String status) {
    return DeliveryStatus.values.firstWhere((value) => value.status == status,
        orElse: () => DeliveryStatus.waiting);
  }
}

 

여기에서 enum을 사용해서 각각의 상태를 체계적으로 관리하기 위함입니다. 보통 직접적으로 데이터를 다룰 때 위와 같이 정해진 값을 사용하는 경우에는 위처럼 enum 등을 사용하여 체계적으로 관리하는 것이 좋습니다. 

 

Step 5: lib > enums > payment_status.dart 파일도 아래처럼 수정해줍니다.

 

enum PaymentStatus {
  //! 상태 열거
  waiting('waiting', '입금대기'),
  completed('completed', '결제완료'),
  cancelled('cancelled', '주문취소');

  //! 생성자
  const PaymentStatus(this.status, this.statusName);

  final String status;
  final String statusName;

  //! 상태 이름 변환
  factory PaymentStatus.getStatusName(String status) {
    return PaymentStatus.values.firstWhere((value) => value.status == status,
        orElse: () => PaymentStatus.waiting);
  }
}

 

 

 

Step 6: 먼저 pubspec.yaml에서 crypto 패키지를 설치해주시고 item_checkout_page.dart 파일로 가셔서 intl, crypto 패키지 임포트 해주신 뒤에 아래 빨간색 박스 내용을 추가합니다. 245-247번째 줄은 비밀번호를 sha256 알고리즘으로 암호화하기 위함이고 248-249번째 줄은 주문번호를 현재 일시에 맞춰서 생성하기 위함입니다. (물론 이 경우에도 중복은 나올 수 있습니다)

 

 

 

Step 7: 빨간 박스 아래에 아래 내용을 추가해줍니다. 이 강좌에서는 한 데이터 document에 여러 제품을 포함할 수 없는 구조이며 무조건 문서 1개당 제품 하나만 담을 수 있는 구조입니다. 그래서 여러 제품을 담는 경우에는 orderNo로 묶어서 표현할 수 있습니다. 실제 업무에서는 아래처럼 하기 보다는 products 변수가 별도로 있어서 배열 형태로 들어가는 것이 권장됩니다. 다만 제 강좌에서는 최대한 간단하게 하기 위해 배제하였습니다. try catch 구문을 넣어 예외 처리 해주시고, database.collection("orders").add 메소드를 통해서 데이터를 추가하면 됩니다. 

 

//! 이 부분에 파이어스토어에 접근해서 데이터 insert 작업 진행함.
                            snapshot.data?.docs.forEach(
                              (document) {
                                ProductOrder productOrder = ProductOrder(
                                  orderNo: orderNo,
                                  productNo: document.data().productNo,
                                  orderDate: DateFormat("y-M-d h:m:s")
                                      .format(DateTime.now()),
                                  buyerName: buyerNameController.text,
                                  buyerEmail: buyerEmailController.text,
                                  buyerPhone: buyerPhoneController.text,
                                  receiverName: receiverNameController.text,
                                  receiverPhone: receiverPhoneController.text,
                                  receiverZip: receiverZipController.text,
                                  receiverAddress1:
                                      receiverAddress1Controller.text,
                                  receiverAddress2:
                                      receiverAddress2Controller.text,
                                  userPwd: hashPwd.toString(),
                                  paymentMethod: selectedPaymentMethod,
                                  quantity: cartMap[
                                      document.data().productNo.toString()],
                                  unitPrice: document.data().price,
                                  totalPrice: cartMap[document
                                          .data()
                                          .productNo
                                          .toString()] *
                                      document.data().price,
                                  paymentStatus:
                                      PaymentStatus.waiting.statusName,
                                  deliveryStatus:
                                      DeliveryStatus.waiting.statusName,
                                );
                                print(jsonEncode(productOrder));
                                try {
                                  database
                                      .collection("orders")
                                      .add(productOrder.toJson());
                                } catch (e) {
                                  showDialog(
                                    context: context,
                                    builder: (context) {
                                      return AlertDialog(
                                        content: Padding(
                                          padding: const EdgeInsets.all(15.0),
                                          child: Column(
                                            mainAxisSize: MainAxisSize.min,
                                            children: [
                                              Center(
                                                  child: Text("오류가 발생 했습니다.")),
                                            ],
                                          ),
                                        ),
                                        actions: [
                                          Center(
                                            child: FilledButton(
                                                onPressed: () =>
                                                    Navigator.pop(context),
                                                child: Text("확인")),
                                          ),
                                        ],
                                      );
                                    },
                                  );
                                  //! 아래 부분이 더 이상 호출되지 않도록 return합니다.
                                  return;
                                }
                              },
                            );

 

예외가 있는 경우 아래처럼 Dialog를 띄워서 오류가 발생했는지 띄워주시면 됩니다. (실제로는 어떤 오류인지까지 표현하는 것이 권장됩니다)

 

 

Step 8: 아래처럼 제품을 담고 입력한 뒤 테스트해봅니다.

 

제가 위 코드에 print로 productOrder 객체를 출력되도록 한 결과는 아래와 같습니다.

 

그리고 아래처럼 주문완료 페이지로 넘어가게 됩니다.

 

 

Step 9: 파이어스토어(Firestore)에서 아래처럼 바로 제품 3개의 주문이 들어간 것을 확인해볼 수 있습니다.

 

다음 시간에는 내가 주문한 데이터들을 확인해볼 수 있도록 작업을 진행하겠습니다. 감사합니다.

 

[전체 소스 코드]

 

[item_checkout_page.dart]

 

 

[유튜브 강좌 영상]

 

https://youtu.be/gGLF5fjYlec

 

 

 

반응형