공유하지 않은 메뉴가 있을 때 영수증 나누는 법
52,500원 저녁 식사를 균등하게 나누면 한 사람이 먹지 않은 메뉴 값을 조용히 부담하지만, 공유하지 않은 항목을 지정하고 세금이 소비를 따르게 하면 이 문제가 해결됩니다.
52,500원 저녁 식사를 균등하게 나누면 한 사람이 7,000원을 더 냅니다. 셋 중 둘이 20,000원짜리 해산물 모둠을 먹었고 나머지 한 명은 먹지 않았는데도, 균등 분배는 세 사람 모두에게 17,500원을 청구합니다. Dimesum은 그 영수증을 하나의 지출로 처리합니다. 위에서는 균등하게 나누고, 20,000원 항목은 그것을 주문한 두 사람만 부담합니다.
공유하지 않은 항목 하나가 섞인 대부분 균등한 영수증은 분배 앱이 가장 자주 처리하는 일인데, Dimesum의 첫 데이터 모델은 그것을 표현하지 못했습니다. 이전 설계는 ITEMIZED를 하나의 분배 방식으로 두어 EQUAL, PERCENT, SHARES와 상호 배타적으로 만들었습니다. 실제 식당 영수증은 그 둘이 동시에 존재합니다.
항목화는 지출의 세부 정보일 뿐, 다른 종류의 분배가 아닙니다
Dimesum의 항목별 지출은 항목을 가지고 있을 뿐인 평범한 지출입니다. 이 지출은 지출이 원래 가진 모든 것을 그대로 유지합니다. 총액, 참여자, 분배 방식, 한 명이나 여러 명의 결제자입니다. 여기에 영수증의 항목들, 그리고 그 아래에 인쇄되는 세금, 팁, 수수료, 할인 같은 부가 항목들을 더합니다.
그런 다음 두 개의 층위가 모든 금액을 결정합니다. 지출의 분배 방식은 아무도 지정되지 않은 항목을 나눕니다. 지정된 사람이 있는 항목은 정확히 그 사람들만 부담하고, 그 밖의 누구도 부담하지 않습니다.
| 층위 | 무엇을 결정하는가 | 적용 대상 |
|---|---|---|
| 지출 분배 방식 | 공유 비용을 어떻게 나누는가: 균등하게, 비율로, 또는 가중 지분으로 | 지정된 사람이 없는 모든 항목 |
| 항목 지정자 | 이 항목을 누가 어떤 비율로 소비했는가 | 해당 항목만 |
가장 적게 먹은 사람이 10,500원을 내는 52,500원 저녁 식사
Asha, Bhavna, Chetan이 저녁을 먹고 위에서는 균등하게 나눕니다. 공유 요리는 30,000원입니다. 해산물 요리는 20,000원인데 Asha와 Bhavna만 먹었습니다. 서비스 요금은 5%이고, Chetan이 52,500원 전액을 결제했습니다.
| 항목 | 금액 | Asha | Bhavna | Chetan |
|---|---|---|---|---|
| 공유 요리, 지정자 없음 | 30,000원 | 10,000원 | 10,000원 | 10,000원 |
| 해산물 모둠, Asha와 Bhavna | 20,000원 | 10,000원 | 10,000원 | 0원 |
| 소계 | 50,000원 | 20,000원 | 20,000원 | 10,000원 |
| 서비스 5%, 소계 기준 | 2,500원 | 1,000원 | 1,000원 | 500원 |
| 총액 | 52,500원 | 21,000원 | 21,000원 | 10,500원 |
Chetan은 52,500원을 결제했고 10,500원을 부담하므로 42,000원을 돌려받습니다. Asha에게서 21,000원, Bhavna에게서 21,000원입니다. 누가 결제했는지는 누가 부담하는지와 무관합니다. 결제자가 거의 먹지 않은 사람이라는 사실은 어떤 몫도 바꾸지 않으며, 그래서 Dimesum은 결제자를 지출 층위에, 지정자를 항목 층위에 둡니다.
세금은 인원수가 아니라 무엇을 먹었는지를 따릅니다
2,500원 서비스 요금 중 Chetan의 몫은 833원이 아니라 500원입니다. 모든 부가 항목은 각자의 항목 소계에 비례해 배분되므로, 음식의 20,000:20,000:10,000 분배가 서비스 요금의 분배도 결정합니다. 인원수로 배분하면 Chetan이 손대지도 않은 요리에 대한 세금을 조용히 물게 됩니다.
따라서 아무것도 주문하지 않은 사람은 세금을 내지 않고 할인도 받지 않습니다. 가중치는 누적 합계가 아니라 부가 항목 적용 전의 소계이며, 덕분에 각 부가 항목의 반올림이 다음 항목의 가중치로 누적되지 않습니다.
부가 항목은 순서대로 적용되므로 할인이 GST 기준액을 옮깁니다
'100,000원, 10% 할인, 5% GST 추가'로 읽히는 영수증은 GST를 90,000원에 매기고 GST 항목은 4,500원입니다. 둘의 순서를 바꾸면 GST는 100,000원에 매겨져 5,000원이 됩니다. 부가 항목은 순서가 있는 목록이고, 백분율은 자기 위치에서의 누적 합계에 적용됩니다. 두 순서 모두 실제 영수증이므로 이 목록은 집합이 아니라 순서가 있는 목록입니다.
각 부가 항목은 자체 position을 가집니다. 삽입 순서나 id 생성기의 단조 증가에 의존한 순서는 데이터베이스 복원 후 모두가 부담하는 금액을 조용히 바꿀 것입니다.
오타와 산술 사이에는 세 가지 검증이 있습니다. 풀은 정액 금액이나 베이시스 포인트 단위의 비율 중 하나만 명시하며 둘 다는 아닙니다. 둘 다 저장하면 숫자와 그 도출 방식을 함께 저장하는 셈이기 때문입니다. 음수 금액은 거부되며, 감액을 표기하는 방법으로 DISCOUNT를 알려 주는 오류가 함께 나옵니다. 100,000 베이시스 포인트를 넘는 비율도 거부되는데, 이는 100%를 뜻하는 10,000 베이시스 포인트보다 훨씬 높게 설정된 상한입니다. 100% 할인은 실제로 있는 할인이기 때문입니다.
| 종류 | 누적 합계에 대한 효과 | 자체 종류인 이유 |
|---|---|---|
TAX | 가산 | 표현상의 차이일 뿐, 계산은 동일함 |
TIP | 가산 | 표현상의 차이일 뿐, 계산은 동일함 |
FEE | 가산 | 표현상의 차이일 뿐, 계산은 동일함 |
DISCOUNT | 감산 | 산술을 바꾸는 유일한 종류, 그래서 방향은 부호가 아니라 종류에서 나옴 |
총액은 항목에서 나오며, 입력한 총액은 체크섬일 뿐입니다
항목별 총액은 도출됩니다. 항목의 합에 부가 항목의 합을 더한 값입니다. 항목이 이미 영수증 금액을 말해 주므로, 별도로 명시된 총액은 첫 번째와 어긋날 수 있는 두 번째 진실의 출처가 됩니다. 영수증을 잘못 입력한 사람은 실제로 오류가 있는 곳인 항목을 고치고, 총액은 그에 따라 바뀝니다. 이미 등록된 영수증을 수정하는 일은 분배를 다시 명시하는 편집을 거치므로, 수정은 덮어쓰기가 아니라 새로운 버전으로 반영됩니다.
클라이언트는 여전히 amount_minor를 보낼 수 있고, 그러면 Dimesum은 그것을 답이 아니라 체크섬으로 취급합니다. 일치는 클라이언트가 같은 영수증을 읽었다는 뜻입니다. 불일치는 돈이 오가기 전에 지출을 멈춥니다.
이전 버전은 명시된 총액이 설명하지 못한 부분에 대해 "Other" 항목을 자동으로 추가했고, 그 차이가 사라지면 항목을 제거했습니다. 그 항목은 작동했고, 이제는 없습니다. 총액을 도출하자 "Other" 항목이 관리하려고 존재했던 문제가 사라졌는데, 그 문제는 총액이 두 번 명시되었기 때문에만 생겼던 것입니다.
EXACT와 항목이 함께 거부되는 이유
EXACT는 각 구성원의 최종 금액을 지정합니다. 항목은 각 구성원의 금액을 도출합니다. 둘을 동시에 쓰면 과잉 결정됩니다. 둘이 일치하면 하나가 불필요하고, 어긋나면 지출에 두 개의 답이 생기는데 어느 쪽이 이기는지 정하는 규칙이 없습니다. Dimesum은 아무도 기억하지 못할 우선순위 규칙으로 정리하는 대신 그 조합을 입구에서 거부합니다.
EQUAL, PERCENT, SHARES는 모두 항목과 결합되는데, 각각이 최종 금액의 집합이 아니라 공유 비용을 나누는 규칙이기 때문입니다.
할인이 1원을 잃던 곳
모든 배분은 최대 잉여 방식을 쓰고, 각각은 자기 총액을 정확히 보존합니다. 이 방식의 동점은 예전에는 가장 낮은 구성원 id로 갔고, 그래서 균등 분배 지출마다 그룹에서 가장 오래된 구성원에게 여분의 1원을 넘겼습니다. 이제 동점은 지출 id의 해시로 순환합니다. 공유 항목은 항목별로 나누지 않고 하나로 모아 한 번에 나누므로, 남는 1원이 영수증의 모든 항목마다 같은 구성원에게 떨어지지 않습니다.
여기서 우리 apportion 함수에는 실제 결함이 있었습니다. Go의 정수 나눗셈은 0을 향해 잘라내므로, 음수 총액이 잘못된 방향으로 내림되어 나머지가 배분되지 않았습니다. 100, 200, 300의 가중치에 걸친 −1,000원이 −999원으로 돌아왔습니다. 사라진 1원은 올바르게 할인된 영수증이 자체 합계 검증에 실패하게 만들었을 것이고, 사용자는 자기 계산이 틀렸다는 말을 들었을 것입니다. 이제 음수 총액은 크기로 배분한 뒤 다시 음수로 되돌립니다.
영수증을 인쇄된 그대로 입력하세요
눈에 보이는 항목을 입력하고, 공유하지 않은 항목을 먹은 사람을 지정하고, 세금과 팁, 수수료, 할인을 영수증에 인쇄된 순서대로 더하세요. Dimesum은 총액을 도출하고, 각 부가 항목을 각자가 소비한 만큼 배분하며, 결제자는 그 계산에서 제외합니다. 다음에 한 요리가 다른 사람들이 주문한 것의 두 배라면, 두 사람의 이름을 붙여 자체 항목으로 추가하세요.
자주 묻는 질문
비싼 메뉴를 시킨 사람이 있을 때 식당 영수증은 어떻게 나누나요?
그 메뉴를 별도 항목으로 두고 그것을 먹은 사람을 지정하세요. Dimesum에서는 나머지 금액이 해당 지출의 자체 규칙, 보통은 균등 분배로 나뉘고, 지정된 항목은 지정된 사람만 부담합니다. 그러면 세금과 서비스 요금은 각자의 소계에 따라 배분되므로, 그 메뉴를 건너뛴 사람은 두 가지 모두를 더 적게 냅니다.
세금과 팁은 균등하게 나눠야 하나요, 아니면 각자 주문한 만큼 내야 하나요?
각자 주문한 만큼입니다. Dimesum은 모든 부가 항목을 인원수가 아니라 각자의 항목 소계에 비례해 배분합니다. 한 사람이 10,000원어치를 먹은 52,500원 저녁 식사에서, 그 사람은 2,500원의 서비스 요금 중 833원이 아니라 500원을 부담합니다. 아무것도 주문하지 않은 사람은 세금을 전혀 내지 않습니다.
할인과 세금의 순서가 영수증 총액을 바꾸나요?
네. 부가 항목은 누적 합계에 순서대로 적용됩니다. 그래서 '100,000원, 10% 할인, 5% GST 추가'로 읽히는 영수증은 GST를 90,000원에 매기고 GST 항목은 4,500원이 됩니다. GST를 먼저 두면 100,000원에 매겨져 5,000원이 됩니다. 정액 10,000원 할인이라면 총액도 달라져서 94,500원과 95,000원이 됩니다.
항목별 영수증에 정확한 금액을 쓸 수 없는 이유가 뭔가요?
EXACT는 각 사람의 최종 금액을 지정하고 항목은 그 금액을 도출하므로, 둘을 합치면 하나의 지출에 두 개의 답이 생깁니다. Dimesum은 아무도 기억하지 못할 우선순위 규칙으로 승자를 고르는 대신 그 조합을 거부합니다. EQUAL, PERCENT, SHARES는 모두 항목과 함께 작동하는데, 각각이 최종 금액의 집합이 아니라 공유된 항목을 나누는 규칙이기 때문입니다.
항목별 영수증의 총액을 직접 입력해야 하나요?
아니요. Dimesum은 항목별 총액을 항목의 합과 부가 항목의 합으로 도출합니다. 각 항목이 이미 영수증 금액을 말해 주기 때문입니다. 클라이언트가 보낸 총액은 체크섬으로 검증되며, 불일치하면 돈이 오가기 전에 지출을 멈춥니다. 잘못된 숫자를 고치려면 그 숫자가 나온 항목을 고쳐야 합니다.