Add coa purchase and vendors

This commit is contained in:
Aditya Siregar
2025-09-12 01:12:11 +07:00
parent c107733add
commit efe09c21e4
86 changed files with 8517 additions and 212 deletions
+55
View File
@@ -0,0 +1,55 @@
package entities
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
type AccountType string
const (
AccountTypeCash AccountType = "cash"
AccountTypeWallet AccountType = "wallet"
AccountTypeBank AccountType = "bank"
AccountTypeCredit AccountType = "credit"
AccountTypeDebit AccountType = "debit"
AccountTypeAsset AccountType = "asset"
AccountTypeLiability AccountType = "liability"
AccountTypeEquity AccountType = "equity"
AccountTypeRevenue AccountType = "revenue"
AccountTypeExpense AccountType = "expense"
)
type Account struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
OrganizationID uuid.UUID `gorm:"type:uuid;not null;index" json:"organization_id" validate:"required"`
OutletID *uuid.UUID `gorm:"type:uuid;index" json:"outlet_id"`
ChartOfAccountID uuid.UUID `gorm:"type:uuid;not null;index" json:"chart_of_account_id" validate:"required"`
Name string `gorm:"not null;size:255" json:"name" validate:"required,min=1,max=255"`
Number string `gorm:"not null;size:50" json:"number" validate:"required,min=1,max=50"`
AccountType AccountType `gorm:"not null;size:20" json:"account_type" validate:"required,oneof=cash wallet bank credit debit asset liability equity revenue expense"`
OpeningBalance float64 `gorm:"type:decimal(15,2);default:0.00" json:"opening_balance"`
CurrentBalance float64 `gorm:"type:decimal(15,2);default:0.00" json:"current_balance"`
Description *string `gorm:"type:text" json:"description"`
IsActive bool `gorm:"default:true" json:"is_active"`
IsSystem bool `gorm:"default:false" json:"is_system"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
Organization Organization `gorm:"foreignKey:OrganizationID" json:"organization,omitempty"`
Outlet *Outlet `gorm:"foreignKey:OutletID" json:"outlet,omitempty"`
ChartOfAccount ChartOfAccount `gorm:"foreignKey:ChartOfAccountID" json:"chart_of_account,omitempty"`
}
func (a *Account) BeforeCreate(tx *gorm.DB) error {
if a.ID == uuid.Nil {
a.ID = uuid.New()
}
return nil
}
func (Account) TableName() string {
return "accounts"
}
+41
View File
@@ -0,0 +1,41 @@
package entities
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
type ChartOfAccount struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
OrganizationID uuid.UUID `gorm:"type:uuid;not null;index" json:"organization_id" validate:"required"`
OutletID *uuid.UUID `gorm:"type:uuid;index" json:"outlet_id"`
ChartOfAccountTypeID uuid.UUID `gorm:"type:uuid;not null;index" json:"chart_of_account_type_id" validate:"required"`
ParentID *uuid.UUID `gorm:"type:uuid;index" json:"parent_id"`
Name string `gorm:"not null;size:255" json:"name" validate:"required,min=1,max=255"`
Code string `gorm:"not null;size:20" json:"code" validate:"required,min=1,max=20"`
Description *string `gorm:"type:text" json:"description"`
IsActive bool `gorm:"default:true" json:"is_active"`
IsSystem bool `gorm:"default:false" json:"is_system"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
Organization Organization `gorm:"foreignKey:OrganizationID" json:"organization,omitempty"`
Outlet *Outlet `gorm:"foreignKey:OutletID" json:"outlet,omitempty"`
ChartOfAccountType ChartOfAccountType `gorm:"foreignKey:ChartOfAccountTypeID" json:"chart_of_account_type,omitempty"`
Parent *ChartOfAccount `gorm:"foreignKey:ParentID" json:"parent,omitempty"`
Children []ChartOfAccount `gorm:"foreignKey:ParentID" json:"children,omitempty"`
Accounts []Account `gorm:"foreignKey:ChartOfAccountID" json:"accounts,omitempty"`
}
func (c *ChartOfAccount) BeforeCreate(tx *gorm.DB) error {
if c.ID == uuid.Nil {
c.ID = uuid.New()
}
return nil
}
func (ChartOfAccount) TableName() string {
return "chart_of_accounts"
}
@@ -0,0 +1,31 @@
package entities
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
type ChartOfAccountType struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
Name string `gorm:"not null;size:100" json:"name" validate:"required,min=1,max=100"`
Code string `gorm:"not null;size:10;unique" json:"code" validate:"required,min=1,max=10"`
Description *string `gorm:"type:text" json:"description"`
IsActive bool `gorm:"default:true" json:"is_active"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
ChartOfAccounts []ChartOfAccount `gorm:"foreignKey:ChartOfAccountTypeID" json:"chart_of_accounts,omitempty"`
}
func (c *ChartOfAccountType) BeforeCreate(tx *gorm.DB) error {
if c.ID == uuid.Nil {
c.ID = uuid.New()
}
return nil
}
func (ChartOfAccountType) TableName() string {
return "chart_of_account_types"
}
+5
View File
@@ -18,6 +18,11 @@ func GetAllEntities() []interface{} {
&Payment{},
&Customer{},
&Table{},
&Vendor{},
&PurchaseOrder{},
&PurchaseOrderItem{},
&PurchaseOrderAttachment{},
&IngredientUnitConverter{},
// Analytics entities are not database tables, they are query results
}
}
@@ -0,0 +1,42 @@
package entities
import (
"time"
"github.com/google/uuid"
)
type IngredientUnitConverter struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
OrganizationID uuid.UUID `gorm:"type:uuid;not null" json:"organization_id"`
IngredientID uuid.UUID `gorm:"type:uuid;not null" json:"ingredient_id"`
FromUnitID uuid.UUID `gorm:"type:uuid;not null" json:"from_unit_id"`
ToUnitID uuid.UUID `gorm:"type:uuid;not null" json:"to_unit_id"`
ConversionFactor float64 `gorm:"type:decimal(15,6);not null" json:"conversion_factor"`
IsActive bool `gorm:"default:true" json:"is_active"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
CreatedBy uuid.UUID `gorm:"type:uuid;not null" json:"created_by"`
UpdatedBy uuid.UUID `gorm:"type:uuid;not null" json:"updated_by"`
// Relationships
Organization *Organization `gorm:"foreignKey:OrganizationID" json:"organization,omitempty"`
Ingredient *Ingredient `gorm:"foreignKey:IngredientID" json:"ingredient,omitempty"`
FromUnit *Unit `gorm:"foreignKey:FromUnitID" json:"from_unit,omitempty"`
ToUnit *Unit `gorm:"foreignKey:ToUnitID" json:"to_unit,omitempty"`
CreatedByUser *User `gorm:"foreignKey:CreatedBy" json:"created_by_user,omitempty"`
UpdatedByUser *User `gorm:"foreignKey:UpdatedBy" json:"updated_by_user,omitempty"`
}
func (IngredientUnitConverter) TableName() string {
return "ingredient_unit_converters"
}
// BeforeCreate hook to set default values
func (iuc *IngredientUnitConverter) BeforeCreate() error {
if iuc.ID == uuid.Nil {
iuc.ID = uuid.New()
}
return nil
}
+91
View File
@@ -0,0 +1,91 @@
package entities
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
type PurchaseOrder struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
OrganizationID uuid.UUID `gorm:"type:uuid;not null" json:"organization_id" validate:"required"`
VendorID uuid.UUID `gorm:"type:uuid;not null" json:"vendor_id" validate:"required"`
PONumber string `gorm:"not null;size:50" json:"po_number" validate:"required,min=1,max=50"`
TransactionDate time.Time `gorm:"type:date;not null" json:"transaction_date" validate:"required"`
DueDate time.Time `gorm:"type:date;not null" json:"due_date" validate:"required"`
Reference *string `gorm:"size:100" json:"reference" validate:"omitempty,max=100"`
Status string `gorm:"not null;size:20;default:'draft'" json:"status" validate:"required,oneof=draft sent approved received cancelled"`
Message *string `gorm:"type:text" json:"message" validate:"omitempty"`
TotalAmount float64 `gorm:"type:decimal(15,2);not null;default:0" json:"total_amount"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
Organization *Organization `gorm:"foreignKey:OrganizationID" json:"organization,omitempty"`
Vendor *Vendor `gorm:"foreignKey:VendorID" json:"vendor,omitempty"`
Items []PurchaseOrderItem `gorm:"foreignKey:PurchaseOrderID" json:"items,omitempty"`
Attachments []PurchaseOrderAttachment `gorm:"foreignKey:PurchaseOrderID" json:"attachments,omitempty"`
}
func (po *PurchaseOrder) BeforeCreate(tx *gorm.DB) error {
if po.ID == uuid.Nil {
id := uuid.New()
po.ID = id
}
return nil
}
func (PurchaseOrder) TableName() string {
return "purchase_orders"
}
type PurchaseOrderItem struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
PurchaseOrderID uuid.UUID `gorm:"type:uuid;not null" json:"purchase_order_id" validate:"required"`
IngredientID uuid.UUID `gorm:"type:uuid;not null" json:"ingredient_id" validate:"required"`
Description *string `gorm:"type:text" json:"description" validate:"omitempty"`
Quantity float64 `gorm:"type:decimal(10,3);not null" json:"quantity" validate:"required,gt=0"`
UnitID uuid.UUID `gorm:"type:uuid;not null" json:"unit_id" validate:"required"`
Amount float64 `gorm:"type:decimal(15,2);not null" json:"amount" validate:"required,gte=0"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
PurchaseOrder *PurchaseOrder `gorm:"foreignKey:PurchaseOrderID" json:"purchase_order,omitempty"`
Ingredient *Ingredient `gorm:"foreignKey:IngredientID" json:"ingredient,omitempty"`
Unit *Unit `gorm:"foreignKey:UnitID" json:"unit,omitempty"`
}
func (poi *PurchaseOrderItem) BeforeCreate(tx *gorm.DB) error {
if poi.ID == uuid.Nil {
id := uuid.New()
poi.ID = id
}
return nil
}
func (PurchaseOrderItem) TableName() string {
return "purchase_order_items"
}
type PurchaseOrderAttachment struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
PurchaseOrderID uuid.UUID `gorm:"type:uuid;not null" json:"purchase_order_id" validate:"required"`
FileID uuid.UUID `gorm:"type:uuid;not null" json:"file_id" validate:"required"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
PurchaseOrder *PurchaseOrder `gorm:"foreignKey:PurchaseOrderID" json:"purchase_order,omitempty"`
File *File `gorm:"foreignKey:FileID" json:"file,omitempty"`
}
func (poa *PurchaseOrderAttachment) BeforeCreate(tx *gorm.DB) error {
if poa.ID == uuid.Nil {
id := uuid.New()
poa.ID = id
}
return nil
}
func (PurchaseOrderAttachment) TableName() string {
return "purchase_order_attachments"
}
+39
View File
@@ -0,0 +1,39 @@
package entities
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
type Vendor struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
OrganizationID uuid.UUID `gorm:"type:uuid;not null" json:"organization_id" validate:"required"`
Name string `gorm:"not null;size:255" json:"name" validate:"required,min=1,max=255"`
Email *string `gorm:"size:255" json:"email" validate:"omitempty,email"`
PhoneNumber *string `gorm:"size:20" json:"phone_number" validate:"omitempty"`
Address *string `gorm:"type:text" json:"address" validate:"omitempty"`
ContactPerson *string `gorm:"size:255" json:"contact_person" validate:"omitempty,max=255"`
TaxNumber *string `gorm:"size:50" json:"tax_number" validate:"omitempty,max=50"`
PaymentTerms *string `gorm:"size:100" json:"payment_terms" validate:"omitempty,max=100"`
Notes *string `gorm:"type:text" json:"notes" validate:"omitempty"`
IsActive bool `gorm:"not null;default:true" json:"is_active"`
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
Organization *Organization `gorm:"foreignKey:OrganizationID" json:"organization,omitempty"`
}
func (v *Vendor) BeforeCreate(tx *gorm.DB) error {
if v.ID == uuid.Nil {
id := uuid.New()
v.ID = id
}
return nil
}
func (Vendor) TableName() string {
return "vendors"
}