ð§ DOMAIN_MODEL.md - Domain Model Specification (āļāđāļāļĄāļđāļĨāļāļģāļĨāļāļāđāļāđāļĄāļ)
This document defines the core business entities, their responsibilities, attributes, business constraints, lifecycles, and validation rules for the SplitDee platform.
āđāļāļāļŠāļēāļĢāļāļāļąāļāļāļĩāđāļāļģāļŦāļāļāđāļāļāļāļīāļāļĩāļāļēāļāļāļļāļĢāļāļīāļāđāļāļāļŦāļĨāļąāļ āļŦāļāđāļēāļāļĩāđāļāļ§āļēāļĄāļĢāļąāļāļāļīāļāļāļāļ āļāļļāļāļĨāļąāļāļĐāļāļ° āļāđāļāļāļģāļāļąāļāļāļēāļāļāļļāļĢāļāļīāļ āļ§āļāļāļĢāļāļĩāļ§āļīāļ āđāļĨāļ°āļāļāļāļēāļĢāļāļĢāļ§āļāļŠāļāļāļāļ§āļēāļĄāļāļđāļāļāđāļāļāļŠāļģāļŦāļĢāļąāļāđāļāļĨāļāļāļāļĢāđāļĄ SplitDee
ðđð āļ āļēāļĐāļēāđāļāļĒ (āļŠāļģāļŦāļĢāļąāļāļāļđāđāđāļāđāļāļēāļ)
1. āđāļāļāļāļīāļāļĩ: User (āļāļđāđāđāļāđāļāļēāļ)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āđāļŠāļāļāļāļķāļāļāļąāļāļāļĩāļāļđāđāđāļāđāđāļāđāļĨāļ°āļāļļāļāļāļĨāļāļĩāđāļĨāļāļāļ°āđāļāļĩāļĒāļāđāļāļĢāļ°āļāļ
- āļāļ§āļēāļĄāļĢāļąāļāļāļīāļāļāļāļ: āļāļąāļāđāļāđāļāļāđāļāļĄāļđāļĨāđāļāļĢāđāļāļĨāđ āļāļąāļāļāļĩāļĒāļ·āļāļĒāļąāļāļāļąāļ§āļāļ āļĢāļēāļĒāļĨāļ°āđāļāļĩāļĒāļāļāđāļāļāļāļēāļāļāļĢāđāļāļĄāđāļāļĒāđāļŠāļģāļŦāļĢāļąāļāļŠāļĢāđāļēāļ QR āđāļāđāļ āđāļĨāļ°āļāļąāļāļāļķāļāļĒāļāļāđāļāļīāļāļĢāļ§āļĄāļŠāđāļ§āļāļāļļāļāļāļĨ
- āļāļļāļāļĨāļąāļāļĐāļāļ° (Attributes):
id(UUID): āļāļąāļ§āļĢāļ°āļāļļāđāļāļāļēāļ°āļāļāļāđāļāđāļĨāļ°āļāļđāđāđāļāđāļāļēāļemail(string): āļāļĩāđāļāļĒāļđāđāļāļĩāđāļĄāļĨāļāļĢāļ°āļāļģāļāļąāļāļāļĩpassword_hash(string): āļĢāļŦāļąāļŠāļāđāļēāļāļāļĩāđāđāļŪāļāļāđāļ§āļĒ Bcryptdisplay_name(string): āļāļ·āđāļāđāļŠāļāļāļāļĨāđāļāļĢāđāļāļĨāđāļŠāļēāļāļēāļĢāļāļ°phone_number(string, optional): āļŦāļĄāļēāļĒāđāļĨāļāđāļāļĢāļĻāļąāļāļāđāļāļĩāđāļāļđāļāļāļąāļāļāļĢāđāļāļĄāđāļāļĒāđavatar_url(string, optional): āļĨāļīāļāļāđāļĢāļđāļāļ āļēāļāđāļāļĢāđāļāļĨāđāļāļđāđāđāļāđis_active(boolean): āļŠāļāļēāļāļ°āļāļ§āļēāļĄāđāļāļĨāļ·āđāļāļāđāļŦāļ§āļāļēāļĢāđāļāđāļāļēāļāļāļąāļāļāļĩ
- āļāļ§āļēāļĄāļŠāļąāļĄāļāļąāļāļāđ (Relationships):
- āđāļāļ·āđāļāļĄāđāļĒāļāļŦāļāļķāđāļāļāđāļāļŦāļĨāļēāļĒāļāļąāļ
GroupMember(āļāļĨāļļāđāļĄāļŠāļĄāļēāļāļīāļāļāļĩāđāđāļāđāļēāļĢāđāļ§āļĄ) - āđāļāļ·āđāļāļĄāđāļĒāļāļŦāļāļķāđāļāļāđāļāļŦāļĨāļēāļĒāļāļąāļ
Bill(āļāļīāļĨāļāļĩāđāļŠāļĢāđāļēāļāļāļķāđāļ) - āđāļāļ·āđāļāļĄāđāļĒāļāļŦāļāļķāđāļāļāđāļāļŦāļĨāļēāļĒāļāļąāļ
ExpenseShare(āļĒāļāļāļŠāđāļ§āļāđāļāđāļāļŦāļāļĩāđāļāļĩāđāļāđāļēāļāļāđāļēāļĒ) - āđāļāļ·āđāļāļĄāđāļĒāļāļŦāļāļķāđāļāļāđāļāļŦāļĨāļēāļĒāļāļąāļ
Payment(āļŦāļĨāļąāļāļāļēāļāļāļēāļĢāđāļāļāđāļāļīāļāļāļĩāđāļĒāļ·āđāļāđāļāđāļēāļĄāļē)
- āđāļāļ·āđāļāļĄāđāļĒāļāļŦāļāļķāđāļāļāđāļāļŦāļĨāļēāļĒāļāļąāļ
- āļāđāļāļāļģāļāļąāļāļāļēāļāļāļļāļĢāļāļīāļ: āļāļĩāđāļĄāļĨāļāđāļāļāđāļĄāđāļāđāļģāļāļąāļ āđāļāļāļĢāđāđāļāļĢāļĻāļąāļāļāđāđāļāđāļāļāđāļāļĄāļđāļĨāđāļĨāļ·āļāļāđāļŠāđ āđāļāđāļāļģāđāļāđāļāļāđāļāļāļĢāļ°āļāļļāļāđāļāļāļŠāļĢāđāļēāļāļāļīāļ§āļāļēāļĢāđāļāļĢāđāļāļĄāđāļāļĒāđāđāļĄāļ·āđāļāļāļđāđāđāļāđāļāļēāļāļāļģāļŦāļāđāļēāļāļĩāđāđāļāđāļāđāļāđāļēāļŦāļāļĩāđ
- āļ§āļāļāļĢāļāļĩāļ§āļīāļ (Lifecycle): āļĨāļāļāļ°āđāļāļĩāļĒāļ (Created) â āđāļāđāļāļēāļāļāļĒāļđāđ (Active) â āļĢāļ°āļāļąāļāļāļąāđāļ§āļāļĢāļēāļ§ (Suspended) â āļĒāļāđāļĨāļīāļāđāļāđāļāļēāļ/āļāļāļāļīāļāļāļąāļ§āļāļ (Deactivated)
- āļāļāļāļēāļĢāļāļĢāļ§āļāļŠāļāļāļāđāļāļĄāļđāļĨ: āļāļĩāđāļĄāļĨāļāđāļāļāļāļĢāļāļāļēāļĄāļĢāļđāļāđāļāļ Regex āļāļ·āđāļāđāļŠāļāļāļāļĨāļĒāļēāļ§ 2 āļāļķāļ 100 āļāļąāļāļāļĢāļ° āđāļāļāļĢāđāđāļāļĢāļĻāļąāļāļāđāđāļāļĒāļĄāļĩ 10 āļŦāļĨāļąāļ (āđāļāđāļ 08XXXXXXXX)
- āļāļēāļĢāļāļĒāļēāļĒāļāļąāļ§āđāļāļāļāļēāļāļ: āļāļąāļāļāļĩ Social Login, āļĢāļēāļĒāļĨāļ°āđāļāļĩāļĒāļāđāļĨāļāļāļĩāđāļāļąāļāļāļĩāļāļāļēāļāļēāļĢ, āļāļļāđāļĄāļāļĢāļąāļāđāļāđāļāļāļēāļĢāđāļāđāļāđāļāļ·āļāļ
2. āđāļāļāļāļīāļāļĩ: Group (āļāļĨāļļāđāļĄāļāļīāļāļāļĢāļĢāļĄ)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āđāļŠāļāļāļāļķāļāļāļ·āđāļāļāļĩāđāđāļāđāļāļāļąāļāļāđāļēāđāļāđāļāđāļēāļĒāļāļāļāļĢāļđāļĄāđāļĄāļ āđāļāļ·āđāļāļāļŠāļāļīāļ āļŦāļĢāļ·āļāļāļāļ°āđāļāļīāļāļāļēāļ
- āļāļ§āļēāļĄāļĢāļąāļāļāļīāļāļāļāļ: āļāļąāļāļāļēāļĢāļāđāļāļĄāļđāļĨāļŠāļĄāļēāļāļīāļ āļāļ§āļāļāļļāļĄāļāļāļāđāļāļāļāļīāļĨ āļāļđāđāļĨāļŠāļąāļāļ§āđāđāļĨāļĩāđāļĒāļāļāļāļāļāļĨāļļāđāļĄ āđāļĨāļ°āļāļ§āļāļāļļāļĄāļāļĨāđāļāļāđāļāļāļāđāļāļāļ§āļēāļĄ
- āļāļļāļāļĨāļąāļāļĐāļāļ° (Attributes):
id(UUID): āļāļąāļ§āļĢāļ°āļāļļāđāļāļāļēāļ°āļāļāļāļāļĨāļļāđāļĄname(string): āļāļ·āđāļāļāļĨāļļāđāļĄdescription(text, optional): āļāļģāļāļāļīāļāļēāļĒāļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđāļāļāļāļāļĨāļļāđāļĄinvite_code(string): āļĢāļŦāļąāļŠāđāļāļīāļāļāļ§āļāđāļāđāļēāļāļĨāļļāđāļĄāļāļ§āļēāļĄāļĒāļēāļ§ 10 āļŦāļĨāļąāļ
- āļāļ§āļēāļĄāļŠāļąāļĄāļāļąāļāļāđ (Relationships):
- āļŦāļāļķāđāļāļāđāļāļŦāļĨāļēāļĒāļāļąāļ
GroupMember(āļŠāļĄāļēāļāļīāļāļāļĨāļļāđāļĄ) - āļŦāļāļķāđāļāļāđāļāļŦāļĨāļēāļĒāļāļąāļ
Bill(āļāļīāļĨāļāđāļēāđāļāđāļāđāļēāļĒ) - āļŦāļāļķāđāļāļāđāļāļŦāļĨāļēāļĒāļāļąāļ
ChatMessage(āđāļāļāļŠāļāļāļāļēāļāļĨāļļāđāļĄ) - āļŦāļāļķāđāļāļāđāļāļŦāļāļķāđāļāļāļąāļ
Pet(āļŠāļąāļāļ§āđāđāļĨāļĩāđāļĒāļāļāļĢāļ°āļāļģāļāļĨāļļāđāļĄ)
- āļŦāļāļķāđāļāļāđāļāļŦāļĨāļēāļĒāļāļąāļ
- āļāđāļāļāļģāļāļąāļāļāļēāļāļāļļāļĢāļāļīāļ: āļāļ·āđāļāļāļĨāļļāđāļĄāļŦāđāļēāļĄāļ§āđāļēāļ āļĢāļŦāļąāļŠāđāļāļīāļāļāļ§āļāļāđāļāļāđāļĄāđāļāđāļģāđāļĨāļ°āļāļĢāļ°āļāļāļāļāđāļ§āļĒāļāļąāļ§āļāļąāļāļĐāļĢāļāļŠāļĄāļāļąāļ§āđāļĨāļ
- āļ§āļāļāļĢāļāļĩāļ§āļīāļ (Lifecycle): āļŠāļĢāđāļēāļāļāļĨāļļāđāļĄ â āđāļāđāļāļēāļāļāļĒāļđāđ â āļāļąāļāđāļāđāļāļāļēāļ§āļĢ (Archived)
- āļāļāļāļēāļĢāļāļĢāļ§āļāļŠāļāļāļāđāļāļĄāļđāļĨ: āļāļ·āđāļāļāļĨāļļāđāļĄāļāđāļāļāļĄāļĩāļāļ§āļēāļĄāļĒāļēāļ§āļĢāļ°āļŦāļ§āđāļēāļ 1 āļāļķāļ 100 āļāļąāļāļāļĢāļ°
3. āđāļāļāļāļīāļāļĩ: GroupMember (āļŠāļĄāļēāļāļīāļāļāļĨāļļāđāļĄ)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āđāļŠāļāļāļāļ§āļēāļĄāļŠāļąāļĄāļāļąāļāļāđāđāļĨāļ°āļāļ§āļēāļĄāđāļāļ·āđāļāļĄāđāļĒāļāļĢāļ°āļŦāļ§āđāļēāļāļāļđāđāđāļāđāļāļēāļāđāļĨāļ°āļāļĨāļļāđāļĄ
- āļāļ§āļēāļĄāļĢāļąāļāļāļīāļāļāļāļ: āļāļ§āļāļāļļāļĄāļāļāļāļēāļāļŠāļīāļāļāļīāđāļāļēāļĢāļāļģāļĢāļēāļĒāļāļēāļĢāđāļĨāļ°āđāļāđāļēāļāļķāļāļāđāļāļĄāļđāļĨāļ āļēāļĒāđāļāļāļĨāļļāđāļĄ
- āļāļļāļāļĨāļąāļāļĐāļāļ° (Attributes):
id(UUID): āļāļąāļ§āļĢāļ°āļāļļāļŠāļāļēāļāļ°āļŠāļĄāļēāļāļīāļgroup_id(UUID): āļāļąāļ§āļāđāļēāļāļāļīāļāļāļĨāļļāđāļĄāļŦāļĨāļąāļuser_id(UUID): āļāļąāļ§āļāđāļēāļāļāļīāļāļāļđāđāđāļāđāļāļēāļrole(string): āļāļāļāļēāļāļŦāļāđāļēāļāļĩāđāļŠāļīāļāļāļīāđ (ownerāļŦāļĢāļ·āļmember)
- āļāđāļāļāļģāļāļąāļāļāļēāļāļāļļāļĢāļāļīāļ: āļāđāļēāđāļāļāļĩāļāļđāđāļāļąāļ
(group_id, user_id)āļāđāļāļāđāļĄāđāļāđāļģāļāļąāļ āļāļđāđāđāļāđāļāļēāļāđāļĄāđāļŠāļēāļĄāļēāļĢāļāđāļāđāļēāļĢāđāļ§āļĄāļāļĨāļļāđāļĄāđāļāļīāļĄāļāđāļģāļāđāļāļāđāļāđ
4. āđāļāļāļāļīāļāļĩ: Bill (āļāļīāļĨāļāđāļēāđāļāđāļāđāļēāļĒ)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āļĢāļēāļĒāļāļēāļĢāļāļąāļāļāļķāļāļāđāļēāđāļāđāļāđāļēāļĒāļŦāļāļķāđāļāļĢāļēāļĒāļāļēāļĢāļāļĩāđāđāļāļīāļāļāļķāđāļāđāļāļāļĨāļļāđāļĄ
- āļāļ§āļēāļĄāļĢāļąāļāļāļīāļāļāļāļ: āļāļąāļāļāļķāļāļāļđāđāļŠāļģāļĢāļāļāļāđāļēāļĒ āļĒāļāļāđāļāļīāļāļĢāļ§āļĄ āļ§āļīāļāļĩāļāļēāļĢāļŦāļēāļĢāđāļāļīāļ āđāļĨāļ°āļŠāļāļēāļāļ°āļāļģāļĢāļ°āļŦāļāļĩāđ
- āļāļļāļāļĨāļąāļāļĐāļāļ° (Attributes):
id(UUID): āļāļąāļ§āļĢāļ°āļāļļāļāļīāļĨgroup_id(UUID): āļāđāļēāļāļāļīāļāļāļĨāļļāđāļĄcreator_id(UUID): āđāļāđāļēāļŦāļāļĩāđāļāļđāđāļŠāļģāļĢāļāļāļāļāļāđāļāļīāļāļāđāļāļtitle(string): āļāļ·āđāļāļāļīāļĨāļāđāļēāđāļāđāļāđāļēāļĒtotal_amount(numeric): āļĒāļāļāđāļāļīāļāļĢāļ§āļĄāļāļāļāļāļīāļĨcategory(string): āļŦāļĄāļ§āļāļŦāļĄāļđāđāļāļīāļĨstatus(string): āļŠāļāļēāļāļ°āļāļīāļĨ (active,settled,locked)
- āļāđāļāļāļģāļāļąāļāļāļēāļāļāļļāļĢāļāļīāļ: āļĒāļāļāđāļāļīāļāļāđāļāļāļĄāļēāļāļāļ§āđāļē 0 āļāļĨāļĢāļ§āļĄāļŠāđāļ§āļāđāļāđāļāļāđāļāļāđāļāđāļēāļāļąāļāļĒāļāļāļĢāļ§āļĄāļāļīāļĨāļāļāļāļĩ
- āļ§āļāļāļĢāļāļĩāļ§āļīāļ (Lifecycle): āļĢāđāļēāļāļāļ â āđāļāļīāļāđāļāđāļāļēāļāļĢāļāļāļģāļĢāļ° â āļāļģāļĢāļ°āļāļĢāļāļāđāļ§āļ â āļĨāđāļāļāļāļīāļĨāļāļēāļ§āļĢ (Locked)
5. āđāļāļāļāļīāļāļĩ: ExpenseShare (āļŠāđāļ§āļāđāļāđāļāļĒāļāļāļŦāļāļĩāđ)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āļĒāļāļāđāļāļīāļāļāđāļēāļāļāđāļēāļĒāļāļĩāđāļĨāļđāļāļŦāļāļĩāđāđāļāđāļĨāļ°āļāļāļāđāļāļāđāļāļāļāļ·āļāđāļŦāđāđāļāđāļēāļŦāļāļĩāđ
- āļāļļāļāļĨāļąāļāļĐāļāļ° (Attributes):
id(UUID): āļāļąāļ§āļĢāļ°āļāļļāļĒāļāļāļāđāļēāļāļāļģāļĢāļ°bill_id(UUID): āļāđāļēāļāļāļīāļāļāļīāļĨāļŦāļĨāļąāļuser_id(UUID): āļāļąāļ§āļĢāļ°āļāļļāļĨāļđāļāļŦāļāļĩāđshare_amount(numeric): āļĒāļāļāđāļāļīāļāļāļĩāđāļāđāļāļāļāđāļēāļĒstatus(string): āļŠāļāļēāļāļ°āļāļģāļĢāļ°āļŦāļāļĩāđ (unpaid,processing,paid)
6. āđāļāļāļāļīāļāļĩ: Payment (āļĢāļēāļĒāļāļēāļĢāļāļģāļĢāļ°āđāļāļīāļ)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āļĢāļēāļĒāļāļēāļĢāļāļģāļĢāļ°āđāļāļīāļāđāļĨāļ°āļāļĢāļ§āļāļŠāļāļāļŦāļĨāļąāļāļāļēāļāļāļāļāļĨāļđāļāļŦāļāļĩāđ
- āļāļļāļāļĨāļąāļāļĐāļāļ° (Attributes):
id(UUID): āļāļąāļ§āļĢāļ°āļāļļbill_id(UUID): āļāđāļēāļāļāļīāļāļāļīāļĨpayer_id(UUID): āļĨāļđāļāļŦāļāļĩāđāļāļđāđāđāļāļāđāļāļīāļamount(numeric): āļĒāļāļāđāļāļīāļāđāļāļāļāļĢāļīāļslip_image_url(string): āļĨāļīāļāļāđāļāļĩāđāđāļāđāļāđāļāļĨāđāļĢāļđāļāļ āļēāļāļŠāļĨāļīāļslip_trans_id(string): āđāļĨāļāļāđāļēāļāļāļīāļāļĢāļŦāļąāļŠāļāļļāļĢāļāļĢāļĢāļĄāļāļāļāļāļāļēāļāļēāļĢverification_status(string): āļŠāļāļēāļāļ°āļāļĢāļ§āļāļŠāļĨāļīāļ (pending,verified,failed)
7. āđāļāļāļāļīāļāļĩ: Receipt (āļ āļēāļāđāļāđāļŠāļĢāđāļāļĢāđāļēāļāļāđāļē)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āļāđāļāļĄāļđāļĨāļŠāđāļāļāđāļāđāļŠāļĢāđāļāļāđāļāļāļēāļāđāļāļ·āđāļāļāļģāļāļ§āļĒāļāļ§āļēāļĄāļŠāļ°āļāļ§āļāđāļāļāļēāļĢāļāļąāļāļŠāļĢāļĢāļāđāļēāđāļāđāļāđāļēāļĒāļŠāļĢāđāļēāļāļāļīāļĨ
8. āđāļāļāļāļīāļāļĩ: Notification (āļāļēāļĢāđāļāđāļāđāļāļ·āļāļ)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āļāļąāļāļāļķāļāđāļĨāļ°āļāļąāļāļŠāđāļāļāđāļāļāļ§āļēāļĄāđāļāđāļāļāđāļēāļ§āļŠāļēāļĢāđāļāļĢāļ°āļāļāđāļāļĒāļąāļāļĄāļ·āļāļāļ·āļāļāļāļāļāļđāđāđāļāđāļāļēāļ
9. āđāļāļāļāļīāļāļĩ: ChatMessage (āļāđāļāļāļ§āļēāļĄāļŠāļāļāļāļē)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āļāđāļāļāļ§āļēāļĄ āļāļīāļāļāļĢāļĢāļĄāļĢāļ°āļāļ āļŦāļĢāļ·āļāļāļēāļĢāđāļāļāļīāļĨāļāļĩāđāđāļŠāļāļāļāļĨāļāļāļŦāđāļāļāđāļāļāļāļāļāļŦāđāļāļ
10. āđāļāļāļāļīāļāļĩ: Pet & PetStatus (āļŠāļąāļāļ§āđāđāļĨāļĩāđāļĒāļāđāļŠāļĄāļ·āļāļāđāļĄāļāļī)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āļŠāļąāļāļ§āđāđāļĨāļĩāđāļĒāļāļāļĢāļ°āļāļģāļŦāđāļāļāļāļāļĒāđāļŠāļāļāļŠāđāļāļāļąāļŠāļāļ§āļēāļĄāļĢāļąāļāļāļīāļāļāļāļāļāļēāļĢāđāļāļīāļāļāđāļēāļāļāļąāļ§āđāļāļĢ XP/HP āļāļāļāļāļĨāļļāđāļĄ
11. āđāļāļāļāļīāļāļĩ: Reminder (āļĢāļēāļĒāļāļēāļĢāļŠāđāļāļāļ§āļ)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āļāļąāļāļāļķāļāļāđāļāļĄāļđāļĨāļāļĢāļ°āļ§āļąāļāļīāļāļēāļĢāļāļāđāļāļ·āļāļāđāļāļīāļāđāļĨāļ°āļĢāļ°āļāļąāļāļāđāļģāđāļŠāļĩāļĒāļāļāļ§āļāđāļāļ·āđāļāļ
12. āđāļāļāļāļīāļāļĩ: AIJob (āļāļīāļ§āļāļēāļ AI)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āļāļēāļāļāļĢāļ°āļĄāļ§āļĨāļāļĨāļĢāļ°āļāļ AI āļŦāļĨāļąāļāļāđāļēāļ āđāļāđāļ āļāļēāļĢāļŠāđāļāļāļ āļēāļāļŠāļĨāļīāļāļāļāļēāļāļēāļĢ
13. āđāļāļāļāļīāļāļĩ: MemeTemplate (āđāļĄāđāđāļāļāļĄāļĩāļĄ)
- āļ§āļąāļāļāļļāļāļĢāļ°āļŠāļāļāđ: āļĢāļđāļāļāļ·āđāļāļŦāļĨāļąāļāļĄāļĩāļĄāđāļĨāļ°āļāđāļāļĄāļđāļĨāļāļīāļāļąāļāļ§āļēāļāļāđāļāļāļ§āļēāļĄāļāļąāļ āļŠāļģāļŦāļĢāļąāļāļĒāļīāļāļāļ§āļāļŦāļāļĩāđāļāļąāļāđāļāļĄāļąāļāļī
ðŽð§ English (For AI Agents)
1. Entity: User
- Purpose: Represents an individual account registered in the system.
- Responsibilities: Holds identity profiles, security credentials, contact details for PromptPay QR generation, and tracks individual financial balance aggregates.
- Attributes:
id(UUID): Unique user identifier.email(string): Account email address.password_hash(string): Bcrypt hash of user password.display_name(string): Public profile display name.phone_number(string, optional): Phone number linked to PromptPay.avatar_url(string, optional): Link to profile avatar.is_active(boolean): Active status flags.
- Relationships:
- One-to-Many with
GroupMember(groups joined). - One-to-Many with
Bill(bills created). - One-to-Many with
ExpenseShare(debts owed). - One-to-Many with
Payment(slips submitted).
- One-to-Many with
- Business Constraints: Email must be unique. Phone number is optional, but required prior to generating PromptPay codes where the user is the creditor.
- Lifecycle: Created (Registered) -> Active -> Suspended (optional) -> Deactivated/Anonymized.
- Validation Rules: Email must match valid email regex. Display name must be between 2 and 100 characters. Phone number must match standard Thai mobile formats (e.g.,
08XXXXXXXXor09XXXXXXXX, total 10 digits). - Future Extensions: Social Login credentials, banking account details, notification preference toggles.
2. Entity: Group
- Purpose: Represents a shared space containing roommates, friends, or travelers who share expenses.
- Responsibilities: Manages memberships, scopes bills, contains a group pet, and scopes chat messages.
- Attributes:
id(UUID): Unique group identifier.name(string): Group name.description(text, optional): Description of the groupâs purpose.invite_code(string): Unique 10-character code to join the group.
- Relationships:
- One-to-Many with
GroupMember(members). - One-to-Many with
Bill(bills). - One-to-Many with
ChatMessage(chat activity feed). - One-to-One with
Pet(shared pet).
- One-to-Many with
- Business Constraints: Name must not be blank. Invite code must be unique and alphanumeric.
- Lifecycle: Created -> Active -> Archived.
- Validation Rules: Group name must be between 1 and 100 characters.
- Future Extensions: Group category, group avatars, group specific thresholds for expenses.
3. Entity: GroupMember
- Purpose: Represents the association between a User and a Group.
- Responsibilities: Governs role permissions inside a group.
- Attributes:
id(UUID): Unique membership identifier.group_id(UUID): Reference to parent Group.user_id(UUID): Reference to associated User.role(string): Member privileges (owner,member).
- Relationships: Many-to-One with
Group, Many-to-One withUser. - Business Constraints: Composite uniqueness on
(group_id, user_id): a user cannot join a group twice. - Lifecycle: Joined -> Active -> Removed/Left.
- Validation Rules: Role must match either
'owner'or'member'.
4. Entity: Bill
- Purpose: Represents a single recorded expense.
- Responsibilities: Tracks who paid, total cost, split logic, and settlement status.
- Attributes:
id(UUID): Unique bill identifier.group_id(UUID): Parent group.creator_id(UUID): The creditor (who paid the initial cost).title(string): Purpose of the bill.total_amount(numeric): Total expense amount.category(string): Expense category.status(string): Status of the bill (active,settled,locked).
- Relationships:
- Many-to-One with
Group. - Many-to-One with
User(creator). - One-to-Many with
ExpenseShare(individual splits). - One-to-Many with
Payment(associated payments).
- Many-to-One with
- Business Constraints: Total amount must be greater than 0. Sum of associated expense shares must exactly equal the total amount.
- Lifecycle: Draft -> Active (Published) -> Settled (all shares paid) -> Locked (archived after verification).
- Validation Rules: Title must be between 1 and 255 characters. Total amount must have up to 2 decimal places.
5. Entity: ExpenseShare
- Purpose: Represents an individual debtorâs share of a specific bill.
- Responsibilities: Tracks debt status and payment details for a single user.
- Attributes:
id(UUID): Unique share identifier.bill_id(UUID): Parent bill.user_id(UUID): Debtor.share_amount(numeric): Amount this user owes.status(string): Status of the share (unpaid,processing,paid).paid_at(datetime, optional): Time of verification.
- Relationships: Many-to-One with
Bill, Many-to-One withUser(debtor). - Business Constraints: Share amount must be positive. Debtor cannot be the same user as the bill creator unless itâs a multi-debtor custom split adjustment.
- Lifecycle: Created -> Unpaid -> Processing (slip uploaded, pending OCR/manual review) -> Paid.
- Validation Rules: Share status must be in
['unpaid', 'processing', 'paid'].
6. Entity: Payment
- Purpose: Represents a transaction submission by a debtor.
- Responsibilities: Houses reference numbers and links to slip photos to verify debt settlement.
- Attributes:
id(UUID): Unique identifier.bill_id(UUID): Associated bill.payer_id(UUID): The debtor who made the payment.amount(numeric): Amount transferred.slip_image_url(string): Path to slip image in secure storage.slip_trans_id(string, optional): Extracted bank transaction ID.verification_status(string): Verification status (pending,verified,failed).verified_at(datetime, optional): Time of verification completion.
- Relationships: Many-to-One with
Bill, Many-to-One withUser(payer). - Business Constraints:
slip_trans_idmust be unique across the entire platform database (prevents double-spending). - Lifecycle: Initiated -> Pending (awaiting OCR/Bank query) -> Verified / Failed.
- Validation Rules: Status must match
['pending', 'verified', 'failed'].
7. Entity: Receipt
- Purpose: Represents the initial invoice or merchant receipt of a bill.
- Responsibilities: Holds details extracted by AI/OCR to auto-populate Bill creation fields.
- Attributes:
id(UUID): Unique identifier.image_url(string): Path to receipt image.extracted_total(numeric, optional): Extracted total cost.extracted_merchant(string, optional): Extracted merchant name.
- Relationships: Associated with
Bill(optional). - Lifecycle: Uploaded -> Extracted -> Linked to Bill / Discarded.
8. Entity: Notification
- Purpose: Represents a system notification to a user.
- Responsibilities: Holds message payload and dispatch status.
- Attributes:
id(UUID): Unique identifier.user_id(UUID): Recipient.title(string): Title of notification.body(text): Content.is_read(boolean): Read status.channel(string): Delivery method (in-app,push).
- Relationships: Many-to-One with
User. - Lifecycle: Created -> Sent -> Read / Expired.
9. Entity: ChatMessage
- Purpose: Represents a message inside a group chat feed.
- Responsibilities: Holds text details, system events, and references to bills/payments.
- Attributes:
id(UUID): Unique identifier.group_id(UUID): Parent group.sender_id(UUID, optional): Sender. If null, represents a system message.message_type(string): Message type (text,system_event,bill_card).message(text): Main message content.metadata_json(JSON, optional): Auxiliary ID references.
- Relationships: Many-to-One with
Group, Many-to-One withUser. - Lifecycle: Sent -> Delivered. No editing allowed.
10. Entity: Pet
- Purpose: Represents the shared virtual pet (âMochiâ) belonging to a group.
- Responsibilities: Motivates timely debt repayment through gamified health status.
- Attributes:
id(UUID): Unique identifier.group_id(UUID): Associated group.pet_name(string): Name chosen by the group.
- Relationships: One-to-One with
Group, One-to-Many withPetStatus. - Lifecycle: Hatched -> Active -> Inactive (group archived).
11. Entity: PetStatus
- Purpose: Represents the dynamic health state of a Pet.
- Responsibilities: Manages level, HP, and Happiness levels.
- Attributes:
id(UUID): Unique identifier.pet_id(UUID): Parent pet.level(integer): Current level.xp(integer): Experience points.hp(integer): Health points (0-100).happiness(integer): Happiness level (0-100).
- Relationships: Many-to-One with
Pet. - Business Constraints: HP and Happiness must be clamped between
0and100. - Lifecycle: Updated daily via cron schedules and whenever payment events trigger updates.
12. Entity: Reminder
- Purpose: Represents a debt-collection notification task.
- Responsibilities: Tracks when, how, and in what tone a debtor was reminded.
- Attributes:
id(UUID): Unique identifier.bill_id(UUID): Reference bill.debtor_id(UUID): Debtor.tone(string): Reminder tone (polite,casual,meme).sent_at(datetime): Time of dispatch.
- Relationships: Many-to-One with
Bill, Many-to-One withUser.
13. Entity: AIJob
- Purpose: Represents an asynchronous background task processed by the AI system (OCR or meme generation).
- Responsibilities: Tracks job status, worker ID, and outputs.
- Attributes:
id(UUID): Unique identifier.job_type(string): Task type (slip_ocr,receipt_ocr,meme_generation).status(string): Status (queued,processing,completed,failed).result(JSON, optional): Output payload.
- Lifecycle: Queued -> Processing -> Completed / Failed.
14. Entity: MemeTemplate
- Purpose: Represents a predefined image layout used to generate AI reminder memes.
- Responsibilities: Holds base paths and coordinates for text placement.
- Attributes:
id(UUID): Unique identifier.name(string): Name of the meme format.image_url(string): Base layout image.text_coordinates(JSON): Pixel boundaries for text overlays.