176 lines
6.7 KiB
Python
176 lines
6.7 KiB
Python
# plugins/exchange/models.py
|
||
|
||
from datetime import datetime
|
||
from sqlalchemy import (
|
||
Column, Integer, ForeignKey, Enum,
|
||
DateTime, Numeric, Text, String, JSON, Boolean
|
||
)
|
||
from app.extensions import db # adjust to your project’s extension import path
|
||
|
||
class Listing(db.Model):
|
||
__tablename__ = 'exchange_listing'
|
||
|
||
id = Column(Integer, primary_key=True)
|
||
plant_id = Column(Integer, ForeignKey('plants.id'), nullable=False)
|
||
|
||
# ownership actors (exactly one should be non-null)
|
||
owner_user_id = Column(Integer, ForeignKey('users.id'), nullable=True)
|
||
owner_vendor_id = Column(Integer, ForeignKey('vendor_vendor.id'), nullable=True)
|
||
owner_group_id = Column(Integer, ForeignKey('groups_group.id'), nullable=True)
|
||
|
||
# listing types
|
||
type = Column(
|
||
Enum(
|
||
'sale','trade','auction','loan','donation',
|
||
'request','consignment','swap',
|
||
name='listing_type'
|
||
),
|
||
nullable=False,
|
||
default='sale'
|
||
)
|
||
|
||
# sale/trade core fields
|
||
bin_price = Column(Numeric, nullable=True) # “Buy It Now” price
|
||
allow_offers = Column(Boolean, default=True) # allow buyer offers
|
||
|
||
# auction-specific
|
||
auction_start = Column(Numeric, nullable=True) # e.g. 0.99
|
||
auction_reserve = Column(Numeric, nullable=True) # e.g. 50.00
|
||
auction_ends_at = Column(DateTime, nullable=True)
|
||
|
||
# trade-specific
|
||
trade_items = Column(JSON, nullable=True) # list of {plant_id, qty, notes}
|
||
|
||
# loan-specific
|
||
loan_return_date = Column(DateTime, nullable=True)
|
||
rental_rate = Column(Numeric, nullable=True)
|
||
|
||
# consignment-specific
|
||
consignment_split= Column(Numeric, nullable=True) # fraction taken as fee (e.g. 0.10)
|
||
|
||
# swap/batch
|
||
swap_batch_id = Column(Integer, ForeignKey('exchange_swapbatch.id'),
|
||
nullable=True)
|
||
|
||
status = Column(
|
||
Enum('active','inactive', name='listing_status'),
|
||
default='active'
|
||
)
|
||
created_at = Column(DateTime, default=datetime.utcnow)
|
||
|
||
|
||
class SwapBatch(db.Model):
|
||
__tablename__ = 'exchange_swapbatch'
|
||
|
||
id = Column(Integer, primary_key=True)
|
||
name = Column(String(128), nullable=False)
|
||
description = Column(Text, nullable=True)
|
||
date = Column(DateTime, nullable=False)
|
||
created_at = Column(DateTime, default=datetime.utcnow)
|
||
|
||
|
||
class Offer(db.Model):
|
||
__tablename__ = 'exchange_offer'
|
||
|
||
id = Column(Integer, primary_key=True)
|
||
listing_id = Column(Integer, ForeignKey('exchange_listing.id'),
|
||
nullable=False)
|
||
|
||
# actor making the offer
|
||
offerer_user_id = Column(Integer, ForeignKey('users.id'), nullable=True)
|
||
offerer_vendor_id = Column(Integer, ForeignKey('vendor_vendor.id'),
|
||
nullable=True)
|
||
offerer_group_id = Column(Integer, ForeignKey('groups_group.id'),
|
||
nullable=True)
|
||
|
||
amount = Column(Numeric, nullable=False)
|
||
notes = Column(Text, nullable=True)
|
||
status = Column(
|
||
Enum('pending','accepted','rejected', name='offer_status'),
|
||
default='pending'
|
||
)
|
||
created_at = Column(DateTime, default=datetime.utcnow)
|
||
responded_at = Column(DateTime, nullable=True)
|
||
|
||
|
||
class Ownership(db.Model):
|
||
__tablename__ = 'exchange_ownership'
|
||
|
||
id = Column(Integer, primary_key=True)
|
||
listing_id = Column(Integer, ForeignKey('exchange_listing.id'),
|
||
nullable=False)
|
||
|
||
# snapshot actor
|
||
owner_user_id = Column(Integer, ForeignKey('users.id'), nullable=True)
|
||
owner_vendor_id = Column(Integer, ForeignKey('vendor_vendor.id'),
|
||
nullable=True)
|
||
owner_group_id = Column(Integer, ForeignKey('groups_group.id'),
|
||
nullable=True)
|
||
|
||
acquired_on = Column(DateTime, nullable=False)
|
||
price_paid = Column(Numeric, nullable=False)
|
||
source_notes = Column(Text, nullable=True)
|
||
|
||
|
||
class OwnershipTransfer(db.Model):
|
||
__tablename__ = 'exchange_ownership_transfer'
|
||
|
||
id = Column(Integer, primary_key=True)
|
||
listing_id = Column(Integer, ForeignKey('exchange_listing.id'),
|
||
nullable=False)
|
||
|
||
# from actor
|
||
from_user_id = Column(Integer, ForeignKey('users.id'), nullable=True)
|
||
from_vendor_id = Column(Integer, ForeignKey('vendor_vendor.id'),
|
||
nullable=True)
|
||
from_group_id = Column(Integer, ForeignKey('groups_group.id'),
|
||
nullable=True)
|
||
|
||
# to actor
|
||
to_user_id = Column(Integer, ForeignKey('users.id'), nullable=True)
|
||
to_vendor_id = Column(Integer, ForeignKey('vendor_vendor.id'),
|
||
nullable=True)
|
||
to_group_id = Column(Integer, ForeignKey('groups_group.id'),
|
||
nullable=True)
|
||
|
||
status = Column(
|
||
Enum('pending','approved','rejected','returned', name='transfer_status'),
|
||
default='pending'
|
||
)
|
||
requested_at = Column(DateTime, default=datetime.utcnow)
|
||
decided_at = Column(DateTime, nullable=True)
|
||
|
||
|
||
class PriceSubmission(db.Model):
|
||
__tablename__ = 'exchange_price_submission'
|
||
|
||
id = Column(Integer, primary_key=True)
|
||
taxon_id = Column(Integer, ForeignKey('botanica_taxon.id'),
|
||
nullable=False)
|
||
listing_id = Column(Integer, ForeignKey('exchange_listing.id'),
|
||
nullable=True)
|
||
|
||
submitter_user_id = Column(Integer, ForeignKey('users.id'),
|
||
nullable=False)
|
||
source_platform = Column(String(64), nullable=False)
|
||
source_vendor_name = Column(String(128), nullable=True)
|
||
original_price = Column(Numeric, nullable=True)
|
||
paid_price = Column(Numeric, nullable=False)
|
||
shipping_price = Column(Numeric, nullable=True)
|
||
tax_amount = Column(Numeric, nullable=True)
|
||
notes = Column(Text, nullable=True)
|
||
submitted_at = Column(DateTime, default=datetime.utcnow)
|
||
|
||
|
||
class UserRating(db.Model):
|
||
__tablename__ = 'exchange_user_rating'
|
||
|
||
id = Column(Integer, primary_key=True)
|
||
rater_id = Column(Integer, ForeignKey('users.id'),
|
||
nullable=False)
|
||
target_user_id = Column(Integer, ForeignKey('users.id'),
|
||
nullable=False)
|
||
score = Column(Integer, nullable=False)
|
||
notes = Column(Text, nullable=True)
|
||
rated_at = Column(DateTime, default=datetime.utcnow)
|