279 lines
9.8 KiB
Python
279 lines
9.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
pyjeeves.models
|
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Jeeves raw data models
|
|
"""
|
|
# from sqlalchemy import Column, String
|
|
from sqlalchemy.schema import MetaData, ForeignKey, Column
|
|
from sqlalchemy.orm import relationship
|
|
from sqlalchemy.types import Integer, String
|
|
from sqlalchemy.ext.automap import automap_base
|
|
from sqlalchemy.ext.hybrid import hybrid_property
|
|
from sqlalchemy.sql.expression import and_
|
|
from sqlalchemy.exc import OperationalError
|
|
|
|
from . import db
|
|
|
|
from pyjeeves import logging
|
|
from .abc import RawBaseModel
|
|
|
|
logger = logging.getLogger("PyJeeves." + __name__)
|
|
logger.info("Reading Jeeves DB structure")
|
|
|
|
meta = MetaData()
|
|
try:
|
|
meta.reflect(bind=db.raw_session.connection(),
|
|
only=['ar', 'ars', 'xae', 'xare', 'fr', 'kus', 'x1k',
|
|
'oh', 'lp', 'vg', 'xp', 'xm', 'prh', 'prl'])
|
|
except OperationalError as e:
|
|
logger.error("Failed to read Jeeves DB structure")
|
|
raise e
|
|
|
|
Base = automap_base(cls=db.Model, name='Model', metadata=meta)
|
|
|
|
|
|
class ProductClass(Base, RawBaseModel):
|
|
__tablename__ = 'xp'
|
|
__column_map__ = {'ArtProdKlass': 'ProductClassNumber', 'ArtProdklBeskr': 'ProductClassName'}
|
|
__to_dict_only__ = ('ArtProdKlass', 'ArtProdklBeskr')
|
|
# print_filter = ('Articles', 'articles_collection')
|
|
|
|
|
|
class ArticleClass(Base, RawBaseModel):
|
|
__tablename__ = 'xm'
|
|
__column_map__ = {'ArtKod': 'ArticleClassNumber', 'ArtTypBeskr': 'ArticleClassName'}
|
|
__to_dict_only__ = ('ArtKod', 'ArtTypBeskr')
|
|
# print_filter = ('Articles', 'articles_collection')
|
|
|
|
|
|
class CommodityGroup(Base, RawBaseModel):
|
|
__tablename__ = 'vg'
|
|
__column_map__ = {'VaruGruppKod': 'CommodityGroupNumber',
|
|
'VaruGruppBeskr': 'CommodityGroupName'}
|
|
__to_dict_only__ = ('VaruGruppKod', 'VaruGruppBeskr', 'ArticleClass')
|
|
print_filter = ('Articles', 'articles_collection')
|
|
# to_json_filter = ('Articles', 'articles_collection')
|
|
|
|
ArtKod = Column(Integer, ForeignKey('xm.ArtKod'), primary_key=True)
|
|
|
|
ArticleClass = relationship(ArticleClass)
|
|
|
|
|
|
class ArticleAlternativeUnit(Base, RawBaseModel):
|
|
__tablename__ = 'xae'
|
|
__column_map__ = {'AltEnhetKod': 'UnitCode', 'AltEnhetBeskr': 'UnitName',
|
|
'AltEnhetOmrFaktor': 'DefaultUnitConv'}
|
|
__to_dict_only__ = ('AltEnhetBeskr', 'AltEnhetOmrFaktor')
|
|
|
|
|
|
class ArticleUnit(Base, RawBaseModel):
|
|
__tablename__ = 'xare'
|
|
__column_map__ = {'ArtNr': 'ArticleNumber',
|
|
'AltEnhetKod': 'UnitCode', 'AltEnhetOmrFaktor': 'UnitConv',
|
|
'AltEnhetOrderStd': 'DefaultSalesUnit'}
|
|
__to_dict_only__ = ('AltEnhetKod', 'AltEnhetOmrFaktor',
|
|
'AltEnhetOrderStd', 'ArticleAlternativeUnit')
|
|
|
|
ArtNr = Column(String, ForeignKey('ar.ArtNr'), primary_key=True)
|
|
|
|
AltEnhetKod = Column(Integer, ForeignKey('xae.AltEnhetKod'), primary_key=True)
|
|
ArticleAlternativeUnit = relationship(ArticleAlternativeUnit)
|
|
|
|
|
|
class ArticleBalance(Base, RawBaseModel):
|
|
__tablename__ = 'ars'
|
|
__column_map__ = {'LagSaldo': 'Balance',
|
|
'LagResAnt': 'ReservedBalance',
|
|
'LagsaldoAltEnh': 'BalanceAlternative',
|
|
'LagResAntAltEnh': 'ReservedAlternativeBalance',
|
|
'LagStalle': 'StorageLocationNumber'}
|
|
__to_dict_only__ = ('LagSaldo',
|
|
'LagResAnt',
|
|
'LagsaldoAltEnh',
|
|
'LagResAntAltEnh',
|
|
'LagStalle')
|
|
# print_filter = ('Article', 'articles_collection')
|
|
# to_json_filter = ('Article', 'articles_collection')
|
|
|
|
ArtNr = Column(Integer, ForeignKey('ar.ArtNr'), primary_key=True)
|
|
|
|
|
|
class Article(Base, RawBaseModel):
|
|
__tablename__ = 'ar'
|
|
|
|
__column_map__ = {'ArtNr': 'ArticleNumber',
|
|
'ArtBeskr': 'ArticleName',
|
|
'ArtBeskrSpec': 'ArticleSpec',
|
|
'Edit': 'ArticleLongSpec',
|
|
'LagSaldoArtikel': 'UnitBalance',
|
|
'EnhetsKod': 'Unit',
|
|
'ArtListPris': 'UnitListPrice',
|
|
'Extra1': 'WholeSaleUnit'}
|
|
__to_dict_only__ = (
|
|
'ArtNr',
|
|
'ArtBeskr',
|
|
'ArtBeskrSpec',
|
|
'Edit',
|
|
'CommodityGroup',
|
|
'ProductClass',
|
|
'ArticleClass',
|
|
'ArticleBalance',
|
|
'EnhetsKod',
|
|
'LagSaldoArtikel',
|
|
'RowCreatedDt',
|
|
'ArtListPris',
|
|
'PictureFileName',
|
|
'UnitListPrice',
|
|
'Extra1',
|
|
'ListPrice',
|
|
'Balance')
|
|
|
|
ArtNr = Column(Integer, primary_key=True)
|
|
|
|
VaruGruppKod = Column(Integer, ForeignKey('vg.VaruGruppKod'), primary_key=True)
|
|
ArtProdKlass = Column(Integer, ForeignKey('xp.ArtProdKlass'), primary_key=True)
|
|
ArtKod = Column(Integer, ForeignKey('xm.ArtKod'), primary_key=True)
|
|
|
|
CommodityGroup = relationship(CommodityGroup, lazy='joined')
|
|
ProductClass = relationship(ProductClass, lazy='joined')
|
|
ArticleClass = relationship(ArticleClass, lazy='joined')
|
|
ArticleBalance = relationship(ArticleBalance)
|
|
|
|
ArticleUnit = relationship(ArticleUnit)
|
|
|
|
def get_unit_conv(self):
|
|
if self.ArtFsgForp:
|
|
return self.ArtFsgForp
|
|
|
|
for unit in self.ArticleUnit:
|
|
if unit.AltEnhetOrderStd == "1":
|
|
if unit.AltEnhetOmrFaktor:
|
|
return unit.AltEnhetOmrFaktor
|
|
else:
|
|
return unit.ArticleAlternativeUnit.AltEnhetOmrFaktor
|
|
|
|
return 1
|
|
|
|
@hybrid_property
|
|
def ListPrice(self):
|
|
try:
|
|
return self.ArtListPris * self.get_unit_conv()
|
|
except TypeError:
|
|
logger.debug("NoneType error, %s" % self.ArtNr)
|
|
|
|
@hybrid_property
|
|
def Balance(self):
|
|
try:
|
|
return self.LagSaldoArtikel / self.get_unit_conv()
|
|
except TypeError:
|
|
logger.debug("NoneType error, %s" % self.ArtNr)
|
|
|
|
@classmethod
|
|
def _base_filters(self, obj):
|
|
return RawBaseModel._base_filters(
|
|
obj,
|
|
and_(obj.LagTyp == 0)
|
|
)
|
|
|
|
|
|
class Company(Base, RawBaseModel):
|
|
__tablename__ = 'fr'
|
|
__column_map__ = {'FtgNr': 'CompanyNumber', 'FtgNamn': 'CompanyName'}
|
|
__to_dict_only__ = ('FtgNr', 'FtgNamn', 'Customer')
|
|
|
|
FtgNr = Column(String, primary_key=True)
|
|
|
|
Customer = relationship('Customer', uselist=False, back_populates='Company', lazy='joined')
|
|
|
|
|
|
class CustomerCategory(Base, RawBaseModel):
|
|
__tablename__ = 'x1k'
|
|
|
|
KundKategoriKod = Column(Integer, primary_key=True)
|
|
|
|
|
|
class Customer(Base, RawBaseModel):
|
|
__tablename__ = 'kus'
|
|
__column_map__ = {'FtgNr': 'CompanyNumber', 'kundkategorikod': 'CustomerCategoryCode',
|
|
'PrisListaKundSpec': 'PriceListPrimary', 'PrisLista': 'PriceListSecondary'}
|
|
__to_dict_only__ = ('kundkategorikod', 'PriceList', 'PriceListCommon', 'CustomerCategory',
|
|
'PrisLista', 'PrisListaKundSpec')
|
|
|
|
FtgNr = Column(String, ForeignKey('fr.FtgNr'), primary_key=True)
|
|
KundKategoriKod = Column(Integer, ForeignKey('x1k.KundKategoriKod'))
|
|
PrisLista = Column(Integer, ForeignKey('prh.PrisLista'))
|
|
PrisListaKundSpec = Column(Integer, ForeignKey('prh.PrisLista'))
|
|
|
|
Company = relationship("Company", back_populates="Customer")
|
|
PriceList = relationship("PriceList", uselist=False,
|
|
lazy='joined', foreign_keys='PriceList.FtgNr')
|
|
|
|
PriceListCommon = relationship("PriceList", uselist=False,
|
|
foreign_keys='PriceList.PrisLista',
|
|
primaryjoin="Customer.PrisLista==PriceList.PrisLista")
|
|
|
|
KundKategori = relationship("CustomerCategory")
|
|
|
|
@hybrid_property
|
|
def CustomerCategory(self):
|
|
return self.KundKategori.KundKatBeskr
|
|
|
|
|
|
class PriceList(Base, RawBaseModel):
|
|
__tablename__ = 'prh'
|
|
__column_map__ = {'PrisListaBeskr': 'Description', 'PrisLista': 'PriceListNumber',
|
|
'MarkUpBelopp': 'PriceFactor'}
|
|
__to_dict_only__ = ('PrisListaBeskr', 'PrisLista', 'PriceListItems', 'MarkUpBelopp')
|
|
|
|
PrisLista = Column(Integer, primary_key=True)
|
|
FtgNr = Column(String, ForeignKey('kus.FtgNr'))
|
|
|
|
Customer = relationship('Customer', uselist=False, foreign_keys='Customer.PrisListaKundSpec')
|
|
PriceListItems = relationship('PriceListItem', back_populates="PriceList", lazy='joined')
|
|
|
|
|
|
class PriceListItem(Base, RawBaseModel):
|
|
__tablename__ = 'prl'
|
|
__column_map__ = {'ArtNr': 'ArticleNumber', 'vb_pris': 'UnitPrice',
|
|
'MarkUpBelopp': 'UnitPriceFactor', 'NollFaktor': 'NullPriceAllowed'}
|
|
__to_dict_only__ = ('ArtNr', 'vb_pris', 'MarkUpBelopp', 'NollFaktor', 'Price')
|
|
__to_dict_filter__ = ['PriceList']
|
|
|
|
# Do not serialize price list relationship
|
|
__dict_args__ = {
|
|
'adapters': {
|
|
**{
|
|
PriceList: None
|
|
},
|
|
**RawBaseModel.__dict_args__['adapters']
|
|
}
|
|
}
|
|
|
|
PrisLista = Column(Integer, ForeignKey('prh.PrisLista'), primary_key=True)
|
|
ArtNr = Column(Integer, ForeignKey('ar.ArtNr'), primary_key=True)
|
|
|
|
PriceList = relationship('PriceList', uselist=False)
|
|
Article = relationship(Article)
|
|
|
|
# TODO: Could likely be optimized by getting all articles in one query and mangled in repo
|
|
@hybrid_property
|
|
def Price(self):
|
|
if not self.vb_pris and not self.MarkUpBelopp:
|
|
return (
|
|
(self.Article.ArtListPris + self.PriceList.MarkUpBelopp) *
|
|
self.Article.get_unit_conv())
|
|
if self.vb_pris:
|
|
return self.vb_pris * self.Article.get_unit_conv()
|
|
else:
|
|
return (
|
|
(self.Article.ArtListPris + self.MarkUpBelopp) *
|
|
self.Article.get_unit_conv())
|
|
|
|
|
|
Base.prepare()
|
|
|
|
# Base companies for cusomters and suppliers
|
|
Order = Base.classes.oh # Orders by customers
|
|
DelivLoc = Base.classes.lp # Connections between a delivery company and customer company
|