어제 밤에 누가 summer version에서는 보이지 않을 수 있다는 것 같아서

오자마자 버전을 확인했지만 아무리 봐도 summer 버전을 사용하는 것이 없었다.

 

신기하게도 구버전 사용하는 메서드들조차 겨울이었고

메서드들은 봄 버전이었다.

마지막으로 sfdc 현재 접속 라이트닝 또한23 Spring이었기 때문에

더 이상 summer와 연관될 내용이 없어 아쉽지만 넘어가기로 했다.

 

dk가 궁금하다고 하셔서 추가적인 테스트를 하고

계정도 5개나 더 생성하면서 trailhead 4개, 개인 dev 2개, 유료판 1개로 테스트했지만

모두 실패해버렸다.

 

확장프로그램의 문제를 제기하신 분도 있지만

다른 브라우저에서도 되지 않았기 때문에 관련이 없을 것 같았다.

 

작업을 하던 중 갑작스럽게 디케이가 오셔서 네임드 크레덴셜의 문제를 알았다고 하시며

갑작스럽게 company information으로 들어가셨는데

원인은 정말 말도 안되게도 통화 설정 부분이 kr-null로 설정되어 있기 때문에

보안쪽에서 작동이 되지 않는다는 것이었는데

korea 거주중인 사람이 아닌 이상 절대 알 수 없는 문제라

어쩐지 sfdx 개발한 사람조차 모르는 문제라는 답변이 나왔었는데

정확한 원인은 모르지만 통화가 null로 찍히면 숫자도 문제가 생기고

숫자가 문제가 생기면 table 구조에 들어가는 숫자 또한 터지기 때문에

결론적으로는 테이블이 생성되는 즉시 그 아래로 데이터가 터져버리는 것이었다.

 

네임드 크레덴셜 부분을 해결했기 때문에

Oauth2 문제도 쉽게 해결할 수 있을 것 같았지만

중간 중간 막혀서 바로 해결되지 않았는데

위니가 핵심 키워드를 알려줘서 해결할 수 있었다.

 

필터링을 진행하면서 @wire(getProducts, {family : '$family', key:'$key'})를 통해 두개의 데이터를 보내고

해당 값을 통해 필터링을 진행할 수 있었고

js 반응등을 할 때 필터링 결과와 무관하게 남아있던 선택 상품 테이블이나

변경했을 때 필터링 결과가 남아있는 등의 자잘한 문제들을 해결했다.

 

테스트코드 및 pmd도 딱히 문제될 것은 없었기 때문에 넘어갈 수 있었고

그 뒤에 정렬이 문제였는데 정렬까지는 어떻게 구현했지만

4개의 파라미터를 넘겨주니 pmd 에러가 발생했다.

 

해당 문제를 해결하기 위해 여러가지 시도를 했지만 결론적으로는 터져서 할 수 없었다.

 

list, object형태로도 시도해보고 JSON형태로도 시도했지만 제대로 도착하지도 못했고

도착한 경우 ‘$xxx’형태로 변경되지 않은 string 자체가 넘어갔다.

 

사실상 4개의 매개변수를 넘기는 것 보다 더 가독성이 떨어질게 분명하고

될지 안될지도 모르는 객체 형태에 통일 후 class wrapper로 받아 쓰기는

굳이 시도하지 않으려고 했지만 질문을 여러곳에한 업보로 다들 구경하셨기 때문에

결국 class 형태도 시도해볼 수 밖에 없었다.

 

전체 변경을 진행했지만 객체라 그런지 추적을 제대로 하지 않았고

결국 const a = {…obj, changed data} 형태로 바꾼 다음

this.obj = a로 모두 주소 변경까지 해줬지만 그래도 되지 않았다.

(생각해보면 구조분해할당으로 한 시점에서 이미 주소가 바뀐다)

 

그래도 apex에서 객체 형태의 데이터를 마음대로 받을 수 있는 wrapper에 대해

조금 더 자세히 알 수 있는 좋은 시간이었던 것 같다.

아래는 객체 적용까지 된 js 전체 코드와 apex 부분 코드다.

//js
import { wire, LightningElement, track } from 'lwc';
import { refreshApex } from "@salesforce/apex";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import getProducts from '@salesforce/apex/BProductController.getProducts';
import productUpdateWithParams from '@salesforce/apex/BProductController.productUpdateWithParams';
import productUpdate from '@salesforce/apex/BProductController.productUpdate';
import template1 from './leather.html'
import template2 from './glass.html'
import template3 from './steel.html'
import template4 from './wood.html'

//변경점
export default class InventoryConsolidation extends LightningElement {
  @track
  dataObj = {
    showTemplate : "leather",
    searchKey : '',
    order : 'ASC',
    sortKey : 'Name'
  }

  render() {
    if (this.dataObj.showTemplate === "leather") return template1;
    else if (this.dataObj.showTemplate === "glass") return template2;
    else if (this.dataObj.showTemplate === "steel") return template3;
    else if (this.dataObj.showTemplate === "wood") return template4;
    return null;
  }
  selectedProducts = [];
  @track selectedData = [];
  @track isSelected = false;
  @track productList;
  wiredData;
  // @wire(getProducts, {family : '$family', key:'$key', sortKey:'$sortKey', ordering:'$ordering'})
  @wire(getProducts, {strObj:'$obj'})
  wiredRecord(result) {
      this.wiredData = result;
      if (result.data) {
          this.productList = JSON.parse(result.data);
      } else if (result.error) {
          console.log(result.error);
      }
  }
  get obj(){
    return this.dataObj
  }
  // get family() {
  //   return this.showTemplate;
  // }
  // get key() {
  //   return this.searchKey;
  // }
  // get ordering() {
  //   return this.order;
  // }
  // get sortKey() {
  //   return this.sort;
  // }

  constructor() {
    super();
    const a = {showTemplate : "leather",
    searchKey : '',
    order : 'ASC',
    sortKey : 'Name'}
    this.dataObj = a
  }
  
  showLeather() {
    this.selectedData = new Array(0);
    this.isSelected = false;
    const a = {showTemplate : "leather",
    searchKey : '',
    ...this.dataObj};
    this.dataObj = a;
  }

  showGlass() {
    this.selectedData = new Array(0);
    this.isSelected = false;
    const a = {showTemplate : "glass",
    searchKey : '',
    ...this.dataObj};
    this.dataObj = a;
  }

  showSteel() {
    this.selectedData = new Array(0);
    this.isSelected = false;
    const a = {showTemplate : "steel",
    searchKey : '',
    ...this.dataObj};
    this.dataObj = a;
  }
  showWood() {
    this.selectedData = new Array(0);
    this.isSelected = false;
    const a = {showTemplate : "wood",
    searchKey : '',
    ...this.dataObj};
    this.dataObj = a;
  }

  filterHandler(e){
    if(e.key === 'Enter'){
      this.selectedData = new Array(0);
      this.isSelected = false;
      const a = {searchKey : e.target.value,
      ...this.dataObj};
      this.dataObj = a;
      return refreshApex(this.wiredData);
    } 
  }
  sortHandler(e){
    const sortTarget = e.target.textContent;

    if(this.dataObj.order === 'ASC'){
      const a = {order : 'DESC',
        ...this.dataObj};
      this.dataObj = a;
    }
    else if(this.dataObj.order === 'DESC'){
      const a = {order : 'ASC',
        ...this.dataObj};
      this.dataObj = a;
    }

    if(sortTarget === '상품명'){
      const a = {sortKey : 'Name',
        ...this.dataObj};
        this.dataObj = a;
    }
    else if(sortTarget === '재고'){
      const a = {sortKey : 'Stock__c',
        ...this.dataObj};
        this.dataObj = a;
    }
    else if(sortTarget === '최종 수정일'){
      const a = {sortKey : 'LastModifiedDate',
        ...this.dataObj};
        this.dataObj = a;
    }

    this.selectedData = new Array(0);
    this.isSelected = false;
    return refreshApex(this.wiredData);
  }

  handleAllChange(event) {
      for (let i = 0; i < this.productList.length; i++) {
          const product = this.productList[i];
          product.isSelected = event.target.checked;
      }
      if(event.target.checked){
          this.selectedData = [...this.productList];
          this.isSelected = true;
      }
      else{
          this.selectedData = new Array(0);
          this.isSelected = false;
      }
  }

  handleCheckChange(event) {
      this.productList[event.target.value].isSelected = event.target.checked;     
      const arr = []
      for(let i = 0 ; i < this.productList.length ; i++){
          if(this.productList[i].isSelected === true){
              arr.push(this.productList[i]);
          }
      }
      this.selectedData = [...arr]
      if(this.selectedData.length > 0){
          this.isSelected = true;
      }
      else{
          this.isSelected = false;
      }
  }

  getSelecteProducts() {
      for (let i = 0; i < this.productList.length; i++) {
          if (this.productList[i].isSelected) {
              this.selectedProducts.push(this.productList[i].parentId);
          }
      }
      console.log(JSON.stringify(this.selectedProducts));
      
      if(this.selectedProducts.length === 0){
          this.dispatchEvent(
            new ShowToastEvent({
              title: "선택된 데이터 없음",
              message: '업데이트 하고 싶은 상품을 선택해주세요',
              variant: "error"
            })
          );
          return
      }
      //family 추가
      productUpdateWithParams({idLists:this.selectedProducts, family : this.showTemplate})
      .then((result)=>{
          if(result === 'done'){
              this.dispatchEvent(
                new ShowToastEvent({
                  title: "최신 데이터 확인",
                  message: "변경 사항이 없습니다.",
                  variant: "success"
                })
              );
          }
          else if(result === 'updated'){
            this.selectedData = new Array(0);
            this.isSelected = false;
              this.dispatchEvent(
                new ShowToastEvent({
                  title: "변경 사항 적용",
                  message: "변경 사항이 적용되었습니다.",
                  variant: "success"
                })
              );
          }
          else{
            this.selectedData = new Array(0);
            this.isSelected = false;
              this.dispatchEvent(
                new ShowToastEvent({
                  title: "삭제 및 변경 확인",
                  message: "삭제된 데이터가 존재합니다.",
                  variant: "success"
                })
              );
          }
          return refreshApex(this.wiredData);
      })
      .catch((error) => {
        this.dispatchEvent(
          new ShowToastEvent({
            title: "에러 발생",
            message: error.message,
            variant: "error"
          })
        );
      })
      this.selectedProducts = new Array(0);
  }

  updateAllProduct(){
    //family 추가
      productUpdate({family : this.dataObj.showTemplate})
      .then(()=>{
          setTimeout(() => {
              this.dispatchEvent(
                new ShowToastEvent({
                  title: "전체 동기화",
                  message: "전체 동기화 완료.",
                  variant: "success"
                })
              );
              this.selectedData = new Array(0);
              this.isSelected = false;
              const arr = []
              for(let i = 0 ; i < this.productList.length ; i++){
                      this.productList[i].isSelected = false;
                      arr.push(this.productList[i]);
              }
              this.selectedData = [...arr]
              let a = this.template.querySelectorAll("lightning-input")[0]
              a.checked = false;
              return refreshApex(this.wiredData);
          }, 100);
      })
      .catch((error) => {
          this.dispatchEvent(
            new ShowToastEvent({
              title: "에러 발생",
              message: error.message,
              variant: "error"
            })
          );
      })
  }
}

//apex
    /**
    * @description : 재고 보기
    * @author Yohan | 2023.05.11
    * @param strObj
    * @return String
    **/
    @AuraEnabled(cacheable=true)
	public static String getProducts(CustomWrapper strObj){
        System.debug(strObj);
        String family = strObj.showTemplate;
        String searchKey = strObj.searchKey + '%';
        String ordering = strObj.order;
        String sortKey = strObj.sortKey;
        List<ProductWrap> productList = new List<ProductWrap>();
        List<Product2> products = new List<Product2>();
        // // List<Product2> products = Database.query('SELECT Name, Stock__c, ProductParentId__c, LastModifiedDate FROM Product2 WHERE Family = :family');
        // // List<Product2> products = Database.query('SELECT Name, Stock__c, ProductParentId__c, LastModifiedDate FROM Product2 WHERE Family = :family AND Name LIKE :searchKey ');
        // // String b = 'SELECT Name, Stock__c, ProductParentId__c, LastModifiedDate FROM Product2 WHERE Family = :family AND Name LIKE :searchKey ORDER BY '+ sortKey + ' ' +ordering;
        // // List<Product2> products = Database.query(b);
        // // String b = sortKey + ' ' + ordering;
        // // List<Product2> products = Database.query('SELECT Name, Stock__c, ProductParentId__c, LastModifiedDate FROM Product2 WHERE Family = :family AND Name LIKE :searchKey ORDER BY :b');

        
            if(sortKey == 'Name'){
                products = Database.query('SELECT Name, Stock__c, ProductParentId__c, LastModifiedDate FROM Product2 WHERE Family = :family AND Name LIKE :searchKey ORDER BY Name ASC');
            }
            else if(sortKey == 'Stock__c'){
                products = Database.query('SELECT Name, Stock__c, ProductParentId__c, LastModifiedDate FROM Product2 WHERE Family = :family AND Name LIKE :searchKey ORDER BY Stock__c ASC');
            }
            else if(sortKey == 'LastModifiedDate'){
                products = Database.query('SELECT Name, Stock__c, ProductParentId__c, LastModifiedDate FROM Product2 WHERE Family = :family AND Name LIKE :searchKey ORDER BY LastModifiedDate ASC');
            }
            else if(ordering == 'DESC'){
            if(sortKey == 'Name'){
                products = Database.query('SELECT Name, Stock__c, ProductParentId__c, LastModifiedDate FROM Product2 WHERE Family = :family AND Name LIKE :searchKey ORDER BY Name DESC');
            }
            else if(sortKey == 'Stock__c'){
                products = Database.query('SELECT Name, Stock__c, ProductParentId__c, LastModifiedDate FROM Product2 WHERE Family = :family AND Name LIKE :searchKey ORDER BY Stock__c DESC');
            }
            else if(sortKey == 'LastModifiedDate'){
                products = Database.query('SELECT Name, Stock__c, ProductParentId__c, LastModifiedDate FROM Product2 WHERE Family = :family AND Name LIKE :searchKey ORDER BY LastModifiedDate DESC');
            }
            }
        for(Product2 a : products){
            productList.add(new ProductWrap(a));
        }
        return JSON.serialize(productList);
	}


    /****************************************************************************************   
    * File Name   : BProductController.cls  
    * @description : 테이블용 상품 정보 wrapper
    * Test Clss   : -  
    * Author      : Yohan  
    * Page        : -
    * Modification Log   
    * ===============================================================   
    * Ver  Date        Author        Modification  
    * ===============================================================  
    * 1.0  2023.05.11  Yohan        타입지정용 클래스, 메서드 생성
    ****************************************************************************************  
    * TODO  
    ****************************************************************************************/ 
    public class ProductWrap{
        public String parentId;
        public String name;
        public Decimal stock;
        public dateTime dates;
        public Boolean isSelected;
        
        /**
        * @description : 상품 재고 확인용 타입 반환
        * @author Yohan | 2023.05.11
        * @param a
        **/
	    public ProductWrap(Product2 a){
            this.parentId = a.ProductParentId__c;
            this.name = a.Name;
            this.stock = a.Stock__c;
            this.dates = a.LastModifiedDate;
            this.isSelected = false;
		}
    }

    /****************************************************************************************   
    * File Name   : BProductController.cls  
    * @description : wire 전달용 클래스 생성
    * Test Clss   : -  
    * Author      : Yohan  
    * Page        : -
    * Modification Log   
    * ===============================================================   
    * Ver  Date        Author        Modification  
    * ===============================================================  
    * 1.0  2023.05.16  Yohan        타입지정용 클래스, 메서드 생성
    ****************************************************************************************  
    * TODO  
    ****************************************************************************************/ 
    public with sharing class CustomWrapper {
        
        /**
        * @description : CustomWrapper 내부 family
        * @author Yohan | 2023.05.16
        **/
        @AuraEnabled
        public String showTemplate { get; set; }
        
        /**
        * @description : CustomWrapper 내부 key
        * @author Yohan | 2023.05.16
        **/
        @AuraEnabled
        public String searchKey { get; set; }
        
        /**
        * @description : CustomWrapper 내부 ordering
        * @author Yohan | 2023.05.16
        **/
        @AuraEnabled
        public String order { get; set; }
        
        /**
        * @description : CustomWrapper 내부 sortKey
        * @author Yohan | 2023.05.16
        **/
        @AuraEnabled
        public String sortKey { get; set; }
    }

}

 

 

 

 

 

(1).백준 11648번 지속은 숫자가 두자리 이상일 경우 행복하며

다음 턴이 되면 각 숫자를 곱해야 하는 문제로 100 => 0 이 되어 1만큼 행복

25 => 10 =>  0  2만큼 행복과 같은 방식이었다.

 

행복한 조건인 10이상임을 체크하기 위해 9보다 클 경우 반복문을 계속해서 돌게 했고

내부에서는 각 자릿수를 잘라 1에 모두 곱한 다음 결과값을 input에 재할당했다.

 

최종적으로 input이 10보다 작아진 경우 적립된 count를 출력해 문제를 해결했다.

let input = 679
let count = 0

while(input > 9){
    count++
    let tempInput = 1
    let arr = String(input).split('').map(Number)
    for(let i = 0 ; i < arr.length ; i++){
        tempInput *= arr[i]
    }
    input = tempInput
}

console.log(count)

'회고' 카테고리의 다른 글

[수습일지] - 53  (0) 2023.05.18
[수습일지] - 52  (0) 2023.05.17
[수습일지] - 50  (0) 2023.05.15
[수습일지] - 49(주말)  (0) 2023.05.14
[수습일지] - 48(주말)  (0) 2023.05.13

+ Recent posts