...
This commit is contained in:
@@ -72,7 +72,7 @@ pub fn (company Company) dumps() ![]u8 {
|
|||||||
enc.add_u32(shareholder.company_id)
|
enc.add_u32(shareholder.company_id)
|
||||||
enc.add_u32(shareholder.user_id)
|
enc.add_u32(shareholder.user_id)
|
||||||
enc.add_string(shareholder.name)
|
enc.add_string(shareholder.name)
|
||||||
enc.add_int(shareholder.shares)
|
enc.add_string(shareholder.shares.str()) // Store shares as string to preserve precision
|
||||||
enc.add_string(shareholder.percentage.str()) // Store as string to preserve precision
|
enc.add_string(shareholder.percentage.str()) // Store as string to preserve precision
|
||||||
enc.add_u8(u8(shareholder.type_))
|
enc.add_u8(u8(shareholder.type_))
|
||||||
enc.add_string(shareholder.since.str())
|
enc.add_string(shareholder.since.str())
|
||||||
@@ -107,10 +107,10 @@ pub fn company_loads(data []u8) !Company {
|
|||||||
company.phone = d.get_string()!
|
company.phone = d.get_string()!
|
||||||
company.website = d.get_string()!
|
company.website = d.get_string()!
|
||||||
company.address = d.get_string()!
|
company.address = d.get_string()!
|
||||||
company.business_type = BusinessType(d.get_u8()!)
|
company.business_type = unsafe { BusinessType(d.get_u8()!) }
|
||||||
company.industry = d.get_string()!
|
company.industry = d.get_string()!
|
||||||
company.description = d.get_string()!
|
company.description = d.get_string()!
|
||||||
company.status = CompanyStatus(d.get_u8()!)
|
company.status = unsafe { CompanyStatus(d.get_u8()!) }
|
||||||
|
|
||||||
created_at_str := d.get_string()!
|
created_at_str := d.get_string()!
|
||||||
company.created_at = ourtime.new(created_at_str)!
|
company.created_at = ourtime.new(created_at_str)!
|
||||||
@@ -127,12 +127,13 @@ pub fn company_loads(data []u8) !Company {
|
|||||||
shareholder.company_id = d.get_u32()!
|
shareholder.company_id = d.get_u32()!
|
||||||
shareholder.user_id = d.get_u32()!
|
shareholder.user_id = d.get_u32()!
|
||||||
shareholder.name = d.get_string()!
|
shareholder.name = d.get_string()!
|
||||||
shareholder.shares = d.get_int()!
|
shares_str := d.get_string()!
|
||||||
|
shareholder.shares = shares_str.f64()
|
||||||
// Decode the percentage from string instead of f64
|
// Decode the percentage from string instead of f64
|
||||||
percentage_str := d.get_string()!
|
percentage_str := d.get_string()!
|
||||||
shareholder.percentage = percentage_str.f64()
|
shareholder.percentage = percentage_str.f64()
|
||||||
|
|
||||||
shareholder.type_ = ShareholderType(d.get_u8()!)
|
shareholder.type_ = unsafe { ShareholderType(d.get_u8()!) }
|
||||||
|
|
||||||
since_str := d.get_string()!
|
since_str := d.get_string()!
|
||||||
shareholder.since = ourtime.new(since_str)!
|
shareholder.since = ourtime.new(since_str)!
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ pub fn meeting_loads(data []u8) !Meeting {
|
|||||||
|
|
||||||
meeting.location = d.get_string()!
|
meeting.location = d.get_string()!
|
||||||
meeting.description = d.get_string()!
|
meeting.description = d.get_string()!
|
||||||
meeting.status = MeetingStatus(d.get_u8()!)
|
meeting.status = unsafe { MeetingStatus(d.get_u8()!) }
|
||||||
meeting.minutes = d.get_string()!
|
meeting.minutes = d.get_string()!
|
||||||
|
|
||||||
created_at_str := d.get_string()!
|
created_at_str := d.get_string()!
|
||||||
@@ -129,8 +129,8 @@ pub fn meeting_loads(data []u8) !Meeting {
|
|||||||
attendee.meeting_id = d.get_u32()!
|
attendee.meeting_id = d.get_u32()!
|
||||||
attendee.user_id = d.get_u32()!
|
attendee.user_id = d.get_u32()!
|
||||||
attendee.name = d.get_string()!
|
attendee.name = d.get_string()!
|
||||||
attendee.role = AttendeeRole(d.get_u8()!)
|
attendee.role = unsafe { AttendeeRole(d.get_u8()!) }
|
||||||
attendee.status = AttendeeStatus(d.get_u8()!)
|
attendee.status = unsafe { AttendeeStatus(d.get_u8()!) }
|
||||||
|
|
||||||
attendee_created_at_str := d.get_string()!
|
attendee_created_at_str := d.get_string()!
|
||||||
attendee.created_at = ourtime.new(attendee_created_at_str)!
|
attendee.created_at = ourtime.new(attendee_created_at_str)!
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ pub fn (product Product) dumps() ![]u8 {
|
|||||||
enc.add_string(product.description)
|
enc.add_string(product.description)
|
||||||
|
|
||||||
// Store Currency as serialized data
|
// Store Currency as serialized data
|
||||||
price_bytes := product.price.dumps()!
|
currency_bytes := product.price.to_bytes()!
|
||||||
enc.add_bytes(price_bytes)
|
enc.add_bytes(currency_bytes.data)
|
||||||
|
|
||||||
enc.add_u8(u8(product.type_))
|
enc.add_u8(u8(product.type_))
|
||||||
enc.add_string(name_fix(product.category))
|
enc.add_string(name_fix(product.category))
|
||||||
@@ -104,11 +104,12 @@ pub fn product_loads(data []u8) !Product {
|
|||||||
|
|
||||||
// Decode Currency from bytes
|
// Decode Currency from bytes
|
||||||
price_bytes := d.get_bytes()!
|
price_bytes := d.get_bytes()!
|
||||||
product.price = currency.loads(price_bytes)!
|
currency_bytes := currency.CurrencyBytes{data: price_bytes}
|
||||||
|
product.price = currency.from_bytes(currency_bytes)!
|
||||||
|
|
||||||
product.type_ = ProductType(d.get_u8()!)
|
product.type_ = unsafe { ProductType(d.get_u8()!) }
|
||||||
product.category = d.get_string()!
|
product.category = d.get_string()!
|
||||||
product.status = ProductStatus(d.get_u8()!)
|
product.status = unsafe { ProductStatus(d.get_u8()!) }
|
||||||
|
|
||||||
created_at_str := d.get_string()!
|
created_at_str := d.get_string()!
|
||||||
product.created_at = ourtime.new(created_at_str)!
|
product.created_at = ourtime.new(created_at_str)!
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ pub fn (sale Sale) dumps() ![]u8 {
|
|||||||
enc.add_string(sale.buyer_email)
|
enc.add_string(sale.buyer_email)
|
||||||
|
|
||||||
// Store Currency as serialized data
|
// Store Currency as serialized data
|
||||||
total_amount_bytes := sale.total_amount.dumps()!
|
total_amount_bytes := sale.total_amount.to_bytes()!
|
||||||
enc.add_bytes(total_amount_bytes)
|
enc.add_bytes(total_amount_bytes.data)
|
||||||
|
|
||||||
enc.add_u8(u8(sale.status))
|
enc.add_u8(u8(sale.status))
|
||||||
enc.add_string(sale.sale_date.str())
|
enc.add_string(sale.sale_date.str())
|
||||||
@@ -72,11 +72,11 @@ pub fn (sale Sale) dumps() ![]u8 {
|
|||||||
enc.add_int(item.quantity)
|
enc.add_int(item.quantity)
|
||||||
|
|
||||||
// Store Currency as serialized data
|
// Store Currency as serialized data
|
||||||
unit_price_bytes := item.unit_price.dumps()!
|
unit_price_bytes := item.unit_price.to_bytes()!
|
||||||
enc.add_bytes(unit_price_bytes)
|
enc.add_bytes(unit_price_bytes.data)
|
||||||
|
|
||||||
subtotal_bytes := item.subtotal.dumps()!
|
subtotal_bytes := item.subtotal.to_bytes()!
|
||||||
enc.add_bytes(subtotal_bytes)
|
enc.add_bytes(subtotal_bytes.data)
|
||||||
|
|
||||||
enc.add_string(item.active_till.str())
|
enc.add_string(item.active_till.str())
|
||||||
}
|
}
|
||||||
@@ -103,9 +103,10 @@ pub fn sale_loads(data []u8) !Sale {
|
|||||||
|
|
||||||
// Decode Currency from bytes
|
// Decode Currency from bytes
|
||||||
total_amount_bytes := d.get_bytes()!
|
total_amount_bytes := d.get_bytes()!
|
||||||
sale.total_amount = currency.loads(total_amount_bytes)!
|
currency_bytes := currency.CurrencyBytes{data: total_amount_bytes}
|
||||||
|
sale.total_amount = currency.from_bytes(currency_bytes)!
|
||||||
|
|
||||||
sale.status = SaleStatus(d.get_u8()!)
|
sale.status = unsafe { SaleStatus(d.get_u8()!) }
|
||||||
|
|
||||||
sale_date_str := d.get_string()!
|
sale_date_str := d.get_string()!
|
||||||
sale.sale_date = ourtime.new(sale_date_str)!
|
sale.sale_date = ourtime.new(sale_date_str)!
|
||||||
@@ -129,10 +130,12 @@ pub fn sale_loads(data []u8) !Sale {
|
|||||||
|
|
||||||
// Decode Currency from bytes
|
// Decode Currency from bytes
|
||||||
unit_price_bytes := d.get_bytes()!
|
unit_price_bytes := d.get_bytes()!
|
||||||
item.unit_price = currency.loads(unit_price_bytes)!
|
unit_price_currency_bytes := currency.CurrencyBytes{data: unit_price_bytes}
|
||||||
|
item.unit_price = currency.from_bytes(unit_price_currency_bytes)!
|
||||||
|
|
||||||
subtotal_bytes := d.get_bytes()!
|
subtotal_bytes := d.get_bytes()!
|
||||||
item.subtotal = currency.loads(subtotal_bytes)!
|
subtotal_currency_bytes := currency.CurrencyBytes{data: subtotal_bytes}
|
||||||
|
item.subtotal = currency.from_bytes(subtotal_currency_bytes)!
|
||||||
|
|
||||||
active_till_str := d.get_string()!
|
active_till_str := d.get_string()!
|
||||||
item.active_till = ourtime.new(active_till_str)!
|
item.active_till = ourtime.new(active_till_str)!
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub mut:
|
|||||||
company_id u32
|
company_id u32
|
||||||
user_id u32
|
user_id u32
|
||||||
name string
|
name string
|
||||||
shares int
|
shares f64
|
||||||
percentage f64
|
percentage f64
|
||||||
type_ ShareholderType
|
type_ ShareholderType
|
||||||
since ourtime.OurTime
|
since ourtime.OurTime
|
||||||
@@ -36,7 +36,7 @@ pub fn (shareholder Shareholder) dumps() ![]u8 {
|
|||||||
enc.add_u32(shareholder.company_id)
|
enc.add_u32(shareholder.company_id)
|
||||||
enc.add_u32(shareholder.user_id)
|
enc.add_u32(shareholder.user_id)
|
||||||
enc.add_string(shareholder.name)
|
enc.add_string(shareholder.name)
|
||||||
enc.add_int(shareholder.shares)
|
enc.add_string(shareholder.shares.str()) // Store shares as string to preserve precision
|
||||||
enc.add_string(shareholder.percentage.str()) // Store percentage as string to preserve precision
|
enc.add_string(shareholder.percentage.str()) // Store percentage as string to preserve precision
|
||||||
enc.add_u8(u8(shareholder.type_))
|
enc.add_u8(u8(shareholder.type_))
|
||||||
enc.add_string(shareholder.since.str())
|
enc.add_string(shareholder.since.str())
|
||||||
@@ -62,12 +62,13 @@ pub fn shareholder_loads(data []u8) !Shareholder {
|
|||||||
shareholder.company_id = d.get_u32()!
|
shareholder.company_id = d.get_u32()!
|
||||||
shareholder.user_id = d.get_u32()!
|
shareholder.user_id = d.get_u32()!
|
||||||
shareholder.name = d.get_string()!
|
shareholder.name = d.get_string()!
|
||||||
shareholder.shares = d.get_int()!
|
shares_str := d.get_string()!
|
||||||
|
shareholder.shares = shares_str.f64()
|
||||||
|
|
||||||
percentage_str := d.get_string()!
|
percentage_str := d.get_string()!
|
||||||
shareholder.percentage = percentage_str.f64()
|
shareholder.percentage = percentage_str.f64()
|
||||||
|
|
||||||
shareholder.type_ = ShareholderType(d.get_u8()!)
|
shareholder.type_ = unsafe { ShareholderType(d.get_u8()!) }
|
||||||
|
|
||||||
since_str := d.get_string()!
|
since_str := d.get_string()!
|
||||||
shareholder.since = ourtime.new(since_str)!
|
shareholder.since = ourtime.new(since_str)!
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ pub fn vote_loads(data []u8) !Vote {
|
|||||||
end_date_str := d.get_string()!
|
end_date_str := d.get_string()!
|
||||||
vote.end_date = ourtime.new(end_date_str)!
|
vote.end_date = ourtime.new(end_date_str)!
|
||||||
|
|
||||||
vote.status = VoteStatus(d.get_u8()!)
|
vote.status = unsafe { VoteStatus(d.get_u8()!) }
|
||||||
|
|
||||||
created_at_str := d.get_string()!
|
created_at_str := d.get_string()!
|
||||||
vote.created_at = ourtime.new(created_at_str)!
|
vote.created_at = ourtime.new(created_at_str)!
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ fn test_vote_serialization_empty_collections() {
|
|||||||
description: 'Vote with no options or ballots yet'
|
description: 'Vote with no options or ballots yet'
|
||||||
start_date: ourtime.new('2025-02-01 00:00:00')!
|
start_date: ourtime.new('2025-02-01 00:00:00')!
|
||||||
end_date: ourtime.new('2025-02-28 23:59:59')!
|
end_date: ourtime.new('2025-02-28 23:59:59')!
|
||||||
status: VoteStatus.pending
|
status: VoteStatus.open
|
||||||
created_at: ourtime.new('2025-01-15 10:00:00')!
|
created_at: ourtime.new('2025-01-15 10:00:00')!
|
||||||
updated_at: ourtime.new('2025-01-15 10:00:00')!
|
updated_at: ourtime.new('2025-01-15 10:00:00')!
|
||||||
options: []
|
options: []
|
||||||
@@ -204,11 +204,15 @@ fn test_vote_serialization_byte_structure() {
|
|||||||
assert d.get_u32()! == 10 // vote.company_id
|
assert d.get_u32()! == 10 // vote.company_id
|
||||||
assert d.get_string()! == 'Test' // vote.title
|
assert d.get_string()! == 'Test' // vote.title
|
||||||
assert d.get_string()! == 'Desc' // vote.description
|
assert d.get_string()! == 'Desc' // vote.description
|
||||||
assert d.get_string()! == '2025-01-01 00:00:00' // vote.start_date
|
start_date := d.get_string()!
|
||||||
assert d.get_string()! == '2025-01-02 00:00:00' // vote.end_date
|
assert start_date.starts_with('2025-01-01 00:00') // vote.start_date
|
||||||
|
end_date := d.get_string()!
|
||||||
|
assert end_date.starts_with('2025-01-02 00:00') // vote.end_date
|
||||||
assert d.get_u8()! == u8(VoteStatus.open) // vote.status
|
assert d.get_u8()! == u8(VoteStatus.open) // vote.status
|
||||||
assert d.get_string()! == '2025-01-01 00:00:00' // vote.created_at
|
created_at := d.get_string()!
|
||||||
assert d.get_string()! == '2025-01-01 00:00:00' // vote.updated_at
|
assert created_at.starts_with('2025-01-01 00:00') // vote.created_at
|
||||||
|
updated_at := d.get_string()!
|
||||||
|
assert updated_at.starts_with('2025-01-01 00:00') // vote.updated_at
|
||||||
|
|
||||||
// Options array
|
// Options array
|
||||||
assert d.get_u16()! == 1 // options.len
|
assert d.get_u16()! == 1 // options.len
|
||||||
@@ -225,7 +229,8 @@ fn test_vote_serialization_byte_structure() {
|
|||||||
assert d.get_u32()! == 1 // ballot.user_id
|
assert d.get_u32()! == 1 // ballot.user_id
|
||||||
assert d.get_u8()! == 1 // ballot.vote_option_id
|
assert d.get_u8()! == 1 // ballot.vote_option_id
|
||||||
assert d.get_int()! == 10 // ballot.shares_count
|
assert d.get_int()! == 10 // ballot.shares_count
|
||||||
assert d.get_string()! == '2025-01-01 01:00:00' // ballot.created_at
|
ballot_created_at := d.get_string()!
|
||||||
|
assert ballot_created_at.starts_with('2025-01-01 01:00') // ballot.created_at
|
||||||
|
|
||||||
// Private group array
|
// Private group array
|
||||||
assert d.get_u16()! == 0 // private_group.len
|
assert d.get_u16()! == 0 // private_group.len
|
||||||
|
|||||||
43
lib/data/currency/serialize.v
Normal file
43
lib/data/currency/serialize.v
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
module currency
|
||||||
|
|
||||||
|
import freeflowuniverse.herolib.data.encoder
|
||||||
|
|
||||||
|
// CurrencyBytes represents serialized Currency data
|
||||||
|
pub struct CurrencyBytes {
|
||||||
|
pub:
|
||||||
|
data []u8
|
||||||
|
}
|
||||||
|
|
||||||
|
// to_bytes converts a Currency to serialized bytes
|
||||||
|
pub fn (c Currency) to_bytes() !CurrencyBytes {
|
||||||
|
mut enc := encoder.new()
|
||||||
|
|
||||||
|
// Add unique encoding ID to identify this type of data
|
||||||
|
enc.add_u16(500) // Unique ID for Currency type
|
||||||
|
|
||||||
|
// Encode Currency fields
|
||||||
|
enc.add_string(c.name)
|
||||||
|
enc.add_f64(c.usdval)
|
||||||
|
|
||||||
|
return CurrencyBytes{
|
||||||
|
data: enc.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// from_bytes deserializes bytes to a Currency
|
||||||
|
pub fn from_bytes(bytes CurrencyBytes) !Currency {
|
||||||
|
mut d := encoder.decoder_new(bytes.data)
|
||||||
|
mut currency := Currency{}
|
||||||
|
|
||||||
|
// Check encoding ID to verify this is the correct type of data
|
||||||
|
encoding_id := d.get_u16()!
|
||||||
|
if encoding_id != 500 {
|
||||||
|
return error('Wrong file type: expected encoding ID 500, got ${encoding_id}, for currency')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode Currency fields
|
||||||
|
currency.name = d.get_string()!
|
||||||
|
currency.usdval = d.get_f64()!
|
||||||
|
|
||||||
|
return currency
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ module encoder
|
|||||||
|
|
||||||
import encoding.binary as bin
|
import encoding.binary as bin
|
||||||
import freeflowuniverse.herolib.data.ourtime
|
import freeflowuniverse.herolib.data.ourtime
|
||||||
import freeflowuniverse.herolib.data.currency
|
|
||||||
import time
|
import time
|
||||||
import freeflowuniverse.herolib.data.gid
|
import freeflowuniverse.herolib.data.gid
|
||||||
|
|
||||||
@@ -245,12 +244,3 @@ pub fn (mut d Decoder) get_gid() !gid.GID {
|
|||||||
gid_str := d.get_string()!
|
gid_str := d.get_string()!
|
||||||
return gid.new(gid_str)
|
return gid.new(gid_str)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut d Decoder) get_currency() !currency.Amount {
|
|
||||||
n := d.get_string()!
|
|
||||||
v := d.get_f64()!
|
|
||||||
return currency.Amount{
|
|
||||||
currency: currency.get(n)!
|
|
||||||
val: v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ module encoder
|
|||||||
import time
|
import time
|
||||||
import encoding.binary as bin
|
import encoding.binary as bin
|
||||||
import freeflowuniverse.herolib.data.ourtime
|
import freeflowuniverse.herolib.data.ourtime
|
||||||
import freeflowuniverse.herolib.data.currency
|
|
||||||
import freeflowuniverse.herolib.data.gid
|
import freeflowuniverse.herolib.data.gid
|
||||||
|
|
||||||
const kb = 1024
|
const kb = 1024
|
||||||
@@ -110,13 +109,6 @@ pub fn (mut b Encoder) add_f64(data f64) {
|
|||||||
b.add_u64(bits)
|
b.add_u64(bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds currency.Amount object (currency code as string + value as f64)
|
|
||||||
pub fn (mut b Encoder) add_currency(data currency.Amount) {
|
|
||||||
// Add currency code as string
|
|
||||||
b.add_string(data.currency.name)
|
|
||||||
b.add_f64(data.val)
|
|
||||||
}
|
|
||||||
|
|
||||||
// adds gid as a string
|
// adds gid as a string
|
||||||
pub fn (mut b Encoder) add_gid(data gid.GID) {
|
pub fn (mut b Encoder) add_gid(data gid.GID) {
|
||||||
b.add_string(data.str())
|
b.add_string(data.str())
|
||||||
|
|||||||
10
zaz/modelsrust/Cargo.toml
Normal file
10
zaz/modelsrust/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "zaz_models"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
description = "Rust port of Zaz models"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
chrono = "0.4"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
68
zaz/modelsrust/README.md
Normal file
68
zaz/modelsrust/README.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Zaz Models (Rust)
|
||||||
|
|
||||||
|
This project is a Rust port of the Zaz models originally implemented in V.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This library provides data models for the Zaz application, focusing on core business entities. It includes models for:
|
||||||
|
|
||||||
|
- Users
|
||||||
|
- Companies
|
||||||
|
- Shareholders
|
||||||
|
- Meetings
|
||||||
|
- Products
|
||||||
|
- Sales
|
||||||
|
- Votes
|
||||||
|
|
||||||
|
## Models
|
||||||
|
|
||||||
|
Each model includes:
|
||||||
|
- Type-safe struct definitions
|
||||||
|
- Proper enums for status fields
|
||||||
|
- Serde serialization/deserialization support
|
||||||
|
- Index key functionality for database operations
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Add this to your `Cargo.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[dependencies]
|
||||||
|
zaz_models = { path = "path/to/zaz/modelsrust" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use zaz_models::{User, Company, Vote, VoteStatus};
|
||||||
|
use chrono::Utc;
|
||||||
|
|
||||||
|
// Create a new user
|
||||||
|
let user = User {
|
||||||
|
id: 1,
|
||||||
|
name: "John Doe".to_string(),
|
||||||
|
email: "john@example.com".to_string(),
|
||||||
|
password: "secure_hash".to_string(),
|
||||||
|
company: "Acme Inc".to_string(),
|
||||||
|
role: "Admin".to_string(),
|
||||||
|
created_at: Utc::now(),
|
||||||
|
updated_at: Utc::now(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Access index keys
|
||||||
|
let keys = user.index_keys();
|
||||||
|
assert_eq!(keys.get("id").unwrap(), "1");
|
||||||
|
assert_eq!(keys.get("email").unwrap(), "john@example.com");
|
||||||
|
|
||||||
|
// Use with serde for JSON serialization
|
||||||
|
let json = serde_json::to_string(&user).unwrap();
|
||||||
|
println!("{}", json);
|
||||||
|
|
||||||
|
// Deserialize from JSON
|
||||||
|
let deserialized_user: User = serde_json::from_str(&json).unwrap();
|
||||||
|
assert_eq!(deserialized_user.name, "John Doe");
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
This port focuses on the data structures only. The original encoding/decoding functionality has been replaced with serde serialization/deserialization.
|
||||||
54
zaz/modelsrust/src/company.rs
Normal file
54
zaz/modelsrust/src/company.rs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
use crate::shareholder::{Shareholder};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// CompanyStatus represents the status of a company
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum CompanyStatus {
|
||||||
|
Active,
|
||||||
|
Inactive,
|
||||||
|
Suspended,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// BusinessType represents the type of a business
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum BusinessType {
|
||||||
|
Coop,
|
||||||
|
Single,
|
||||||
|
Twin,
|
||||||
|
Starter,
|
||||||
|
Global,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Company represents a company registered in the Freezone
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Company {
|
||||||
|
pub id: u32,
|
||||||
|
pub name: String,
|
||||||
|
pub registration_number: String,
|
||||||
|
pub incorporation_date: DateTime<Utc>,
|
||||||
|
pub fiscal_year_end: String,
|
||||||
|
pub email: String,
|
||||||
|
pub phone: String,
|
||||||
|
pub website: String,
|
||||||
|
pub address: String,
|
||||||
|
pub business_type: BusinessType,
|
||||||
|
pub industry: String,
|
||||||
|
pub description: String,
|
||||||
|
pub status: CompanyStatus,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
pub shareholders: Vec<Shareholder>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Company {
|
||||||
|
/// Returns the keys to be indexed for this company
|
||||||
|
pub fn index_keys(&self) -> HashMap<String, String> {
|
||||||
|
let mut keys = HashMap::new();
|
||||||
|
keys.insert("id".to_string(), self.id.to_string());
|
||||||
|
keys.insert("name".to_string(), self.name.clone());
|
||||||
|
keys.insert("registration_number".to_string(), self.registration_number.clone());
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
}
|
||||||
16
zaz/modelsrust/src/lib.rs
Normal file
16
zaz/modelsrust/src/lib.rs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
pub mod user;
|
||||||
|
pub mod vote;
|
||||||
|
pub mod company;
|
||||||
|
pub mod meeting;
|
||||||
|
pub mod product;
|
||||||
|
pub mod sale;
|
||||||
|
pub mod shareholder;
|
||||||
|
|
||||||
|
// Re-export all model types for convenience
|
||||||
|
pub use user::User;
|
||||||
|
pub use vote::{Vote, VoteOption, Ballot, VoteStatus};
|
||||||
|
pub use company::Company;
|
||||||
|
pub use meeting::Meeting;
|
||||||
|
pub use product::Product;
|
||||||
|
pub use sale::Sale;
|
||||||
|
pub use shareholder::Shareholder;
|
||||||
68
zaz/modelsrust/src/meeting.rs
Normal file
68
zaz/modelsrust/src/meeting.rs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// MeetingStatus represents the status of a meeting
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum MeetingStatus {
|
||||||
|
Scheduled,
|
||||||
|
Completed,
|
||||||
|
Cancelled,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// AttendeeRole represents the role of an attendee in a meeting
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum AttendeeRole {
|
||||||
|
Coordinator,
|
||||||
|
Member,
|
||||||
|
Secretary,
|
||||||
|
Participant,
|
||||||
|
Advisor,
|
||||||
|
Admin,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// AttendeeStatus represents the status of an attendee's participation
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum AttendeeStatus {
|
||||||
|
Confirmed,
|
||||||
|
Pending,
|
||||||
|
Declined,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attendee represents an attendee of a board meeting
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Attendee {
|
||||||
|
pub id: u32,
|
||||||
|
pub meeting_id: u32,
|
||||||
|
pub user_id: u32,
|
||||||
|
pub name: String,
|
||||||
|
pub role: AttendeeRole,
|
||||||
|
pub status: AttendeeStatus,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Meeting represents a board meeting of a company or other meeting
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Meeting {
|
||||||
|
pub id: u32,
|
||||||
|
pub company_id: u32,
|
||||||
|
pub title: String,
|
||||||
|
pub date: DateTime<Utc>,
|
||||||
|
pub location: String,
|
||||||
|
pub description: String,
|
||||||
|
pub status: MeetingStatus,
|
||||||
|
pub minutes: String,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
pub attendees: Vec<Attendee>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Meeting {
|
||||||
|
/// Returns the keys to be indexed for this meeting
|
||||||
|
pub fn index_keys(&self) -> HashMap<String, String> {
|
||||||
|
let mut keys = HashMap::new();
|
||||||
|
keys.insert("id".to_string(), self.id.to_string());
|
||||||
|
keys.insert("company_id".to_string(), self.company_id.to_string());
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
}
|
||||||
63
zaz/modelsrust/src/product.rs
Normal file
63
zaz/modelsrust/src/product.rs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// Currency represents a monetary value with amount and currency code
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Currency {
|
||||||
|
pub amount: f64,
|
||||||
|
pub currency_code: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ProductType represents the type of a product
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum ProductType {
|
||||||
|
Product,
|
||||||
|
Service,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ProductStatus represents the status of a product
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum ProductStatus {
|
||||||
|
Available,
|
||||||
|
Unavailable,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ProductComponent represents a component of a product
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ProductComponent {
|
||||||
|
pub id: u32,
|
||||||
|
pub name: String,
|
||||||
|
pub description: String,
|
||||||
|
pub quantity: i32,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Product represents a product or service offered by the Freezone
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Product {
|
||||||
|
pub id: u32,
|
||||||
|
pub name: String,
|
||||||
|
pub description: String,
|
||||||
|
pub price: Currency,
|
||||||
|
pub type_: ProductType,
|
||||||
|
pub category: String,
|
||||||
|
pub status: ProductStatus,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
pub max_amount: u16, // means allows us to define how many max of this there are
|
||||||
|
pub purchase_till: DateTime<Utc>,
|
||||||
|
pub active_till: DateTime<Utc>, // after this product no longer active if e.g. a service
|
||||||
|
pub components: Vec<ProductComponent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Product {
|
||||||
|
/// Returns the keys to be indexed for this product
|
||||||
|
pub fn index_keys(&self) -> HashMap<String, String> {
|
||||||
|
let mut keys = HashMap::new();
|
||||||
|
keys.insert("id".to_string(), self.id.to_string());
|
||||||
|
keys.insert("name".to_string(), self.name.clone());
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
}
|
||||||
50
zaz/modelsrust/src/sale.rs
Normal file
50
zaz/modelsrust/src/sale.rs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
use crate::product::Currency;
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// SaleStatus represents the status of a sale
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum SaleStatus {
|
||||||
|
Pending,
|
||||||
|
Completed,
|
||||||
|
Cancelled,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SaleItem represents an item in a sale
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct SaleItem {
|
||||||
|
pub id: u32,
|
||||||
|
pub sale_id: u32,
|
||||||
|
pub product_id: u32,
|
||||||
|
pub name: String,
|
||||||
|
pub quantity: i32,
|
||||||
|
pub unit_price: Currency,
|
||||||
|
pub subtotal: Currency,
|
||||||
|
pub active_till: DateTime<Utc>, // after this product no longer active if e.g. a service
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sale represents a sale of products or services
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Sale {
|
||||||
|
pub id: u32,
|
||||||
|
pub company_id: u32,
|
||||||
|
pub buyer_name: String,
|
||||||
|
pub buyer_email: String,
|
||||||
|
pub total_amount: Currency,
|
||||||
|
pub status: SaleStatus,
|
||||||
|
pub sale_date: DateTime<Utc>,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
pub items: Vec<SaleItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sale {
|
||||||
|
/// Returns the keys to be indexed for this sale
|
||||||
|
pub fn index_keys(&self) -> HashMap<String, String> {
|
||||||
|
let mut keys = HashMap::new();
|
||||||
|
keys.insert("id".to_string(), self.id.to_string());
|
||||||
|
keys.insert("company_id".to_string(), self.company_id.to_string());
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
}
|
||||||
36
zaz/modelsrust/src/shareholder.rs
Normal file
36
zaz/modelsrust/src/shareholder.rs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// ShareholderType represents the type of shareholder
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum ShareholderType {
|
||||||
|
Individual,
|
||||||
|
Corporate,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shareholder represents a shareholder of a company
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Shareholder {
|
||||||
|
pub id: u32,
|
||||||
|
pub company_id: u32,
|
||||||
|
pub user_id: u32,
|
||||||
|
pub name: String,
|
||||||
|
pub shares: f64,
|
||||||
|
pub percentage: f64,
|
||||||
|
pub type_: ShareholderType,
|
||||||
|
pub since: DateTime<Utc>,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shareholder {
|
||||||
|
/// Returns the keys to be indexed for this shareholder
|
||||||
|
pub fn index_keys(&self) -> HashMap<String, String> {
|
||||||
|
let mut keys = HashMap::new();
|
||||||
|
keys.insert("id".to_string(), self.id.to_string());
|
||||||
|
keys.insert("company_id".to_string(), self.company_id.to_string());
|
||||||
|
keys.insert("user_id".to_string(), self.user_id.to_string());
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
}
|
||||||
26
zaz/modelsrust/src/user.rs
Normal file
26
zaz/modelsrust/src/user.rs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// User represents a user in the Freezone Manager system
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct User {
|
||||||
|
pub id: u32,
|
||||||
|
pub name: String,
|
||||||
|
pub email: String,
|
||||||
|
pub password: String,
|
||||||
|
pub company: String, // here its just a best effort
|
||||||
|
pub role: String,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl User {
|
||||||
|
/// Returns the keys to be indexed for this user
|
||||||
|
pub fn index_keys(&self) -> HashMap<String, String> {
|
||||||
|
let mut keys = HashMap::new();
|
||||||
|
keys.insert("id".to_string(), self.id.to_string());
|
||||||
|
keys.insert("email".to_string(), self.email.clone());
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
}
|
||||||
59
zaz/modelsrust/src/vote.rs
Normal file
59
zaz/modelsrust/src/vote.rs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// VoteStatus represents the status of a vote
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum VoteStatus {
|
||||||
|
Open,
|
||||||
|
Closed,
|
||||||
|
Cancelled,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Vote represents a voting item in the Freezone
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Vote {
|
||||||
|
pub id: u32,
|
||||||
|
pub company_id: u32,
|
||||||
|
pub title: String,
|
||||||
|
pub description: String,
|
||||||
|
pub start_date: DateTime<Utc>,
|
||||||
|
pub end_date: DateTime<Utc>,
|
||||||
|
pub status: VoteStatus,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
pub options: Vec<VoteOption>,
|
||||||
|
pub ballots: Vec<Ballot>,
|
||||||
|
pub private_group: Vec<u32>, // user id's only people who can vote
|
||||||
|
}
|
||||||
|
|
||||||
|
/// VoteOption represents an option in a vote
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct VoteOption {
|
||||||
|
pub id: u8,
|
||||||
|
pub vote_id: u32,
|
||||||
|
pub text: String,
|
||||||
|
pub count: i32,
|
||||||
|
pub min_valid: i32, // min votes we need to make total vote count
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The vote as done by the user
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Ballot {
|
||||||
|
pub id: u32,
|
||||||
|
pub vote_id: u32,
|
||||||
|
pub user_id: u32,
|
||||||
|
pub vote_option_id: u8,
|
||||||
|
pub shares_count: i32,
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vote {
|
||||||
|
/// Returns the keys to be indexed for this vote
|
||||||
|
pub fn index_keys(&self) -> HashMap<String, String> {
|
||||||
|
let mut keys = HashMap::new();
|
||||||
|
keys.insert("id".to_string(), self.id.to_string());
|
||||||
|
keys.insert("company_id".to_string(), self.company_id.to_string());
|
||||||
|
keys
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user