This commit is contained in:
han0
2024-05-29 10:21:31 +08:00
commit 54ac29d27b
119 changed files with 6817 additions and 0 deletions

View File

@@ -0,0 +1,176 @@
from datetime import datetime
import time
from nc_http.tools.helpers import camelize
from sqlalchemy.orm.exc import NoResultFound
from commons.models.atomic import Atomic
class BaseModel:
query = None
_unique_fields = []
_db = None
__table__ = None
@classmethod
def atomic(cls):
return Atomic(db=cls._db)
@classmethod
def get_by_id(cls, id_, session=None):
if session:
query = session.query(cls)
else:
query = cls.query
result = query.filter((getattr(cls, 'id', None) or cls.__table__.primary_key) == id_).one_or_none()
return result
@classmethod
def insert_many(cls, dicts, commit=True, session=None):
session = session or cls._db.session()
session.bulk_insert_mappings(cls, dicts)
if commit:
session.commit()
@classmethod
def insert_one(cls, values, commit=True, session=None, return_obj=False):
session = session or cls._db.session()
if not return_obj:
session.bulk_insert_mappings(cls, [values])
else:
obj = cls()
for key, value in values.items():
setattr(obj, key, value)
session.add(obj)
if commit:
session.commit()
if return_obj:
return obj
return
@classmethod
def update_one(cls, values, commit=True, session=None):
session = session or cls._db.session()
session.bulk_update_mappings(cls, [values])
if commit:
session.commit()
@classmethod
def update_many(cls, dicts, commit=True, session=None):
session = session or cls._db.session()
session.bulk_update_mappings(cls, dicts)
if commit:
session.commit()
def to_dict(self, is_camelized=True):
_ = {}
for column in self.__table__.columns:
key = getattr(column, 'quote', None) or column.name
if is_camelized:
_[camelize(key)] = getattr(self, key, None)
else:
_[key] = getattr(self, key, None)
return _
@classmethod
def select_one(cls, query, fields=None):
try:
result = query.one()
except NoResultFound:
return {}
if not result:
return {}
return dict(zip([i.key for i in fields], result))
@classmethod
def test_one(cls):
result = cls.query.first()
return result.to_dict()
@classmethod
def now(cls):
return int(time.time())
@classmethod
def now_datetime(cls):
return datetime.fromtimestamp(int(time.time()))
@classmethod
def get_all(cls):
objects = cls.query.all()
for obj in objects:
yield obj.to_dict()
def update(self, commit=True, session=None, **kwargs):
for key, value in kwargs.items():
if hasattr(self, key):
setattr(self, key, value)
if commit:
session = session or self._db.session()
session.commit()
return
def delete(self, session=None):
session = session or self._db.session()
session.delete(self)
@classmethod
def get_list(cls, query, paging=None, fields=None):
if fields:
query = query.with_entities(*fields.values())
if paging:
page = query.paginate(paging['page'], paging['limit'])
paging['total'] = page.total
result = page.items
else:
result = query.all()
if fields:
columns = fields.keys()
result = [dict(zip(columns, _)) for _ in result]
else:
result = [_.to_dict() for _ in result]
if paging:
return result, paging
return result
@classmethod
def set_order_by(cls, query, sorting=None):
"""
配置查询结果排序
:param query:
:param sorting:
:return:
"""
if not sorting or not isinstance(sorting, dict):
return query
order_field = sorting.get('order_field')
if not order_field:
return query
order = sorting.get('order')
if order == 'desc':
query = query.order_by(getattr(cls, order_field).desc())
else:
query = query.order_by(getattr(cls, order_field))
return query

View File

@@ -0,0 +1,50 @@
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint, func
from commons.models.mixin.calculator import CalculatorMixin
from core.extensions import db
class AsphaltDomestic(db.Model, CalculatorMixin):
__tablename__ = 'ASPHALT_DOMESTIC'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
date = Column('DATE', Date, comment='日期')
from_ = Column('FROM', Date, comment='数据来源')
__table_args__ = (
UniqueConstraint(name, date, from_, name='Idx_key'),
{'comment': '国产沥青'},
)
@classmethod
def get_by_key(cls, name, date, from_):
query = cls.query
query = query.filter(
cls.name == name,
cls.date == date,
cls.from_ == from_,
)
return query.one_or_none()
@classmethod
def get_items(cls, date, name_in):
query = cls.query
query = query.filter(cls.date == date)
query = query.filter(cls.name.in_(name_in))
query = query.with_entities(cls.name, func.avg(cls.price))
query = query.group_by(cls.name)
result = query.all()
return result
def upsert(self):
result = self.get_by_key(self.name, self.date, self.from_)
if not result:
session = db.session
session.add(self)
session.commit()
else:
session = db.session
self.id = result.id
session.add(result)
session.commit()

View File

@@ -0,0 +1,48 @@
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint, func
from commons.models.mixin.calculator import CalculatorMixin
from core.extensions import db
class AsphaltImported(db.Model, CalculatorMixin):
__tablename__ = 'ASPHALT_IMPORTED'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, date, name='Idx_key'),
{'comment': '进口沥青'},
)
@classmethod
def get_items(cls, year, month, name_in):
query = cls.query
query = cls.query_by_month(query, year, month)
query = query.filter(cls.name.in_(name_in))
query = query.with_entities(cls.name, func.avg(cls.price))
query = query.group_by(cls.name)
result = query.all()
return result
@classmethod
def get_by_key(cls, name, date):
query = cls.query
query = query.filter(
cls.name == name,
cls.date == date,
)
return query.one_or_none()
def upsert(self):
result = self.get_by_key(self.name, self.date)
if not result:
session = db.session
session.add(self)
session.commit()
else:
session = db.session
self.id = result.id
session.add(result)
session.commit()

View File

@@ -0,0 +1,36 @@
import datetime
from dateutil.relativedelta import relativedelta
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint
from core.extensions import db
class AsphaltModifier(db.Model):
__tablename__ = 'ASPHALT_MODIFIER'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, spec, date, name='Idx_key'),
{'comment': '沥青改性剂'},
)
@classmethod
def get_query(cls, year=None, month=None, name=None, spec=None, name_in=None):
query = cls.query
if year and month:
start_date = datetime.date(year, month, 1)
end_date = start_date + relativedelta(months=1)
query = query.filter(cls.date >= start_date)
query = query.filter(cls.date < end_date)
if name:
query = query.filter(cls.name == name)
if name_in:
query = query.filter(cls.name.in_(name_in))
if spec:
query = query.filter(cls.spec == spec)
return query

View File

@@ -0,0 +1,23 @@
from sqlalchemy.orm import sessionmaker
class Atomic:
def __init__(self, db, session=None):
self.session = session or sessionmaker(bind=db.engine)() # 此处 session 复用会导致事务异常 应创建 session
def __enter__(self):
return self.session
def __exit__(self, exc_type, exc_value, exc_tb):
if exc_tb is None:
try:
self.session.commit()
except Exception as e:
self.session.rollback()
raise e
finally:
self.session.close()
else:
return False
return True

View File

@@ -0,0 +1,20 @@
from sqlalchemy import Column, Integer, String, Date, Text
from core.extensions import db
class Budget(db.Model):
__tablename__ = 'BUDGET'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
amount = Column('AMOUNT', Integer, default='', comment='总数')
min_amount = Column('MIN_AMOUNT', Integer, default='', comment='最小值')
max_amount = Column('MAX_AMOUNT', Integer, default='', comment='最大值')
year = Column('YEAR', Integer, default=0, comment='年份')
months = Column('MONTHS', Text, default='', comment='月份')
date = Column('DATE', Date, comment='日期')
# __table_args__ = (
# UniqueConstraint(name, date, name='Idx_key'),
# {'comment': '预算'},
# )

View File

@@ -0,0 +1,20 @@
from sqlalchemy import Column, Integer, String, Text
from core.extensions import db
class BudgetItem(db.Model):
__tablename__ = 'BUDGET_ITEM'
id = Column('ID', Integer, primary_key=True)
budget_id = Column('BUDGET_ID', Integer, default='', comment='预算id')
name = Column('NAME', String(128), default='', comment='名称')
meta = Column('META', Text, default='', comment='数据')
quantity = Column('QUANTITY', Integer, default='', comment='数量')
unit = Column('UNIT', Text, default='', comment='单位')
unit_Price = Column('UNIT_PRICE', Integer, default='', comment='单价')
total_Price = Column('TOTAL_PRICE', Integer, default='', comment='总价')
# __table_args__ = (
# UniqueConstraint(name, date, name='Idx_key'),
# {'comment': '预算细项'},
# )

View File

@@ -0,0 +1,59 @@
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint, func
from commons.models.mixin.calculator import CalculatorMixin
from core.extensions import db
class Cement(db.Model, CalculatorMixin):
__tablename__ = 'CEMENT'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
pack = Column('PACK', String(64), default='', comment='包装')
source = Column('SOURCE', String(64), default='', comment='产地')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
fluctuating = Column('FLUCTUATING', Numeric(16, 4), default=0, comment='浮动')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, spec, pack, source, date, name='Idx_key'),
{'comment': '水泥'},
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@classmethod
def get_items(cls, year, month, spec_in, name_in, pack):
query = cls.query
query = cls.query_by_month(query, year, month)
query = query.filter(cls.pack == pack)
query = query.filter(cls.spec.in_(spec_in))
query = query.filter(cls.name.in_(name_in))
query = query.with_entities(func.avg(cls.price))
result = query.all()
return result
@classmethod
def get_by_key(cls, name, spec, pack, source, date):
query = cls.query
query = query.filter(
cls.name == name,
cls.spec == spec,
cls.pack == pack,
cls.source == source,
cls.date == date,
)
return query.one_or_none()
def upsert(self):
result = self.get_by_key(self.name, self.spec, self.pack, self.source, self.date)
if not result:
session = db.session
session.add(self)
session.commit()
else:
session = db.session
self.id = result.id
session.add(result)
session.commit()

View File

@@ -0,0 +1,40 @@
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint
from commons.models.mixin.base import BaseModelMixin
from commons.models.model import Model
from core.extensions import db
class DataFujian(db.Model, Model, BaseModelMixin):
__tablename__ = 'DATA_FUJIAN'
id = Column('ID', Integer, primary_key=True)
number = Column('NUMBER', String(128), default='', comment='编码')
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
unit = Column('UNIT', String(128), default='', comment='单位')
price_without_tax = Column('PRICE_WITHOUT_TAX', Numeric(16, 4), default=0, comment='除价格')
price = Column('PRICE', Numeric(16, 4), default=0, comment='含税价')
category = Column('CATEGORY', String(128), default='', comment='分类')
year = Column('YEAR', Integer, default=0, comment='年份')
month = Column('MONTH', Integer, default=0, comment='月份')
city = Column('CITY', String(128), default='', comment='地市')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(year, month, city, name, spec, name='Idx_key'),
{'comment': '福建数据'},
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def find_by_key(self):
query = DataFujian.query
query = query.filter(DataFujian.year == self.year)
query = query.filter(DataFujian.month == self.month)
query = query.filter(DataFujian.city == self.city)
query = query.filter(DataFujian.name == self.name)
query = query.filter(DataFujian.spec == self.spec)
result = query.one_or_none()
return result

View File

@@ -0,0 +1,30 @@
from sqlalchemy import Column, Integer, String, Date, UniqueConstraint
from commons.models.mixin.base import BaseModelMixin
from commons.models.model import Model
from core.extensions import db
class DataGuangdong(db.Model, Model, BaseModelMixin):
__tablename__ = 'DATA_GUANGDONG'
id = Column('ID', Integer, primary_key=True)
url = Column('URL', String(512), default='', comment='下载地址')
name = Column('NAME', String(128), default='', comment='名称')
source = Column('SOURCE', String(128), default='', comment='来源')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, date, name='Idx_key'),
{'comment': '广东数据'},
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def find_by_key(self):
query = DataGuangdong.query
query = query.filter(DataGuangdong.name == self.name)
query = query.filter(DataGuangdong.date == self.date)
result = query.one_or_none()
return result

View File

@@ -0,0 +1,30 @@
from sqlalchemy import Column, Integer, String, Date, UniqueConstraint
from commons.models.mixin.base import BaseModelMixin
from commons.models.model import Model
from core.extensions import db
class DataZhejiang(db.Model, Model, BaseModelMixin):
__tablename__ = 'DATA_ZHEJIANG'
id = Column('ID', Integer, primary_key=True)
url = Column('URL', String(512), default='', comment='下载地址')
name = Column('NAME', String(128), default='', comment='名称')
source = Column('SOURCE', String(128), default='', comment='来源')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, date, name='Idx_key'),
{'comment': '浙江数据'},
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def find_by_key(self):
query = DataZhejiang.query
query = query.filter(DataZhejiang.name == self.name)
query = query.filter(DataZhejiang.date == self.date)
result = query.one_or_none()
return result

View File

@@ -0,0 +1,40 @@
import datetime
from dateutil.relativedelta import relativedelta
from sqlalchemy import Column, Integer, String, Date, UniqueConstraint, Numeric
from core.extensions import db
class FujianSurvey(db.Model):
__tablename__ = 'FUJIAN_SURVEY'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
date = Column('DATE', Date, comment='日期')
material_id = Column('MATERIAL_ID', String(128), comment='材料id')
unit = Column('UNIT', String(128), comment='单位')
brand = Column('BRAND', String(128), comment='品牌')
tax = Column('TAX', Integer, comment='税率')
__table_args__ = (
UniqueConstraint(name, spec, date, name='Idx_key'),
{'comment': '福建省交通工程材料调查表'},
)
@classmethod
def get_query(cls, year=None, month=None, name=None, spec=None, name_in=None):
query = cls.query
if year and month:
start_date = datetime.date(year, month, 1)
end_date = start_date + relativedelta(months=1)
query = query.filter(cls.date >= start_date)
query = query.filter(cls.date < end_date)
if name:
query = query.filter(cls.name == name)
if name_in:
query = query.filter(cls.name.in_(name_in))
if spec:
query = query.filter(cls.spec == spec)
return query

View File

@@ -0,0 +1,36 @@
import datetime
from dateutil.relativedelta import relativedelta
from sqlalchemy import Column, Integer, String, Date, UniqueConstraint, Numeric
from core.extensions import db
class FuzhouHighwayBureau(db.Model):
__tablename__ = 'FUZHOU_HIGHWAY_BUREAU'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
date = Column('DATE', Date, comment='日期')
material_id = Column('MATERIAL_ID', String(128), comment='材料id')
unit = Column('UNIT', String(128), comment='单位')
brand = Column('BRAND', String(128), comment='品牌')
__table_args__ = (
UniqueConstraint(name, spec, date, name='Idx_key'),
{'comment': '福州公路局'},
)
@classmethod
def get_query(cls, year, month, name, spec=None):
start_date = datetime.date(year, month, 1)
end_date = start_date + relativedelta(months=1)
query = cls.query
query = query.filter(cls.date >= start_date)
query = query.filter(cls.date < end_date)
if name:
query = query.filter(cls.name == name)
if spec:
query = query.filter(cls.spec == spec)
return query

View File

@@ -0,0 +1,34 @@
import datetime
from dateutil.relativedelta import relativedelta
from sqlalchemy import Column, Integer, String, Date, UniqueConstraint, Numeric
from core.extensions import db
class FuzhouTransportationBureau(db.Model):
__tablename__ = 'FUZHOU_TRANSPORTATION_BUREAU'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
date = Column('DATE', Date, comment='日期')
material_id = Column('MATERIAL_ID', String(128), comment='材料id')
unit = Column('UNIT', String(128), comment='单位')
brand = Column('BRAND', String(128), comment='品牌')
__table_args__ = (
UniqueConstraint(name, spec, date, name='Idx_key'),
{'comment': '福州交通局'},
)
@classmethod
def get_query(cls, year, month, name):
start_date = datetime.date(year, month, 1)
end_date = start_date + relativedelta(months=1)
query = cls.query
query = query.filter(cls.date >= start_date)
query = query.filter(cls.date < end_date)
if name:
query = query.filter(cls.name == name)
return query

View File

@@ -0,0 +1,24 @@
from sqlalchemy import Column, Integer, String, Date, UniqueConstraint, Numeric, Text
from core.extensions import db
class LocalMaterial(db.Model):
__tablename__ = 'LOCAL_MATERIAL'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
city = Column('CITY', String(128), default='', comment='地市')
county = Column('COUNTY', String(128), default='', comment='区县')
material_id = Column('MATERIAL_ID', String(128), comment='材料id')
spec = Column('SPEC', String(128), default='', comment='规格')
unit = Column('UNIT', String(128), default='', comment='单位')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
price_without_tax = Column('PRICE_WITHOUT_TAX', Numeric(16, 4), default=0, comment='除税价')
date = Column('DATE', Date, comment='日期')
position = Column('POSITION', String(256), comment='位置')
remark = Column('REMARK', Text, comment='备注')
__table_args__ = (
UniqueConstraint(name, spec, city, county, date, name='Idx_key'),
{'comment': '地材'},
)

View File

@@ -0,0 +1,44 @@
from sqlalchemy import Column, Integer, String
from commons.models.mixin.operation_track import OperationTrackMixin
from core.extensions import db
class Material(db.Model, OperationTrackMixin):
id = Column('ID', String(128), primary_key=True)
parent_id = Column('PARENT_ID', String(128))
category_1 = Column('CATEGORY1', String(128), default='', comment='分类1')
category_2 = Column('CATEGORY2', String(128), default='', comment='分类2')
category_3 = Column('CATEGORY3', String(128), default='', comment='分类3')
category_4 = Column('CATEGORY4', String(128), default='', comment='分类4')
name = Column('NAME', String(128), default='', comment='名称')
unit = Column('UNIT', String(128), default='', comment='单位')
spec = Column('SPEC', String(128), default='', comment='规格')
tax = Column('TAX', Integer, default=0, comment='税率(%')
is_builtin = Column('IS_BUILTIN', Integer, default=0, comment='是否初始内建类型(不允许删除)')
type = Column('TYPE', Integer, default=0, comment='材料类别(主材、地材)')
is_tree = Column('IS_TREE', Integer, default=0, comment='是否树')
__tablename__ = 'MATERIAL'
__table_args__ = (
{'comment': '材料'},
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@classmethod
def get_by_key(cls, id):
return cls.query.filter(cls.id == id).one_or_none()
def upsert(self):
result = self.get_by_key(self.id)
if not result:
session = db.session
session.add(self)
session.commit()
else:
session = db.session
self.id = result.id
session.add(result)
session.commit()

View File

@@ -0,0 +1,22 @@
from sqlalchemy import Column, Integer, String
from sqlalchemy.dialects.mysql import MEDIUMTEXT
from commons.models.mixin.operation_track import OperationTrackMixin
from commons.models.model import Model
from core.extensions import db
class MaterialTask(db.Model, OperationTrackMixin, Model):
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='任务名称')
status = Column('STATUS', Integer, default=0, comment='状态(待采集、已采集、采集中)')
file = Column('FILE', String(256), default='', comment='文件路径')
type = Column('TYPE', Integer, default=0, comment='类型(网络爬取、文件上传)')
year = Column('YEAR', Integer, default=0, comment='采集年份')
month = Column('MONTH', Integer, default=0, comment='采集月份')
content = Column('CONTENT', MEDIUMTEXT, comment='数据内容')
__tablename__ = 'MATERIAL_TASK'
__table_args__ = (
{'comment': '采集任务'},
)

View File

View File

@@ -0,0 +1,13 @@
class BaseModelMixin:
def find_by_key(self):
...
def upsert(self):
result = self.find_by_key()
session = self._db.session
if result:
session.delete(result)
session.flush()
session.add(self)
session.commit()

View File

@@ -0,0 +1,28 @@
class CalculatorMixin:
date = None
@classmethod
def query_by_month(cls, query, year, month):
last_month_year, last_month = Helper.get_last_month(year, month)
query = query.filter(cls.date >= datetime.date(last_month_year, last_month, 26))
query = query.filter(cls.date <= datetime.date(year, month, 25))
return query
def upsert(self, *args, **kwargs):
result = self.get_by_key(*args, **kwargs)
if not result:
session = db.session
session.add(self)
session.commit()
else:
session = db.session
self.id = result.id
session.add(result)
session.commit()
@classmethod
def get_last_date_from(cls, date):
query = cls.query.filter(cls.date <= date)
query = query.with_entities(func.max(cls.date))
result = query.one_or_none()
return result[0]

View File

@@ -0,0 +1,23 @@
class EsSourceMixin:
__table__ = None
__tablename__ = ''
def to_es(self):
primary_key_name = [str(i.name) for i in self.__table__.columns if i.primary_key][0]
es_data = {
'meta': {
'id': '{}/{}'.format(self.__tablename__, getattr(self, primary_key_name)),
},
'table': self.__tablename__,
'create_time': self.now() * 1000,
}
return es_data
@classmethod
def get_es_data(cls):
for item in cls.query.yield_per(500):
yield item.to_es()
@classmethod
def es_join_str(cls, str_list):
return ' '.join(str(i or '') for i in str_list if i)

View File

@@ -0,0 +1,51 @@
from nc_http.tools.helpers import camelize
class InsensitiveMixin:
__table__ = None
_sensitive_columns = []
def to_insensitive_dict(self, is_camelized=True):
"""
对象转字典且不带敏感数据 <例:密码、密钥、手机号...>
:return:
"""
if self._sensitive_columns:
_ = {}
for column in self.__table__.columns:
if column in self._sensitive_columns:
continue
key = getattr(column, 'quote', None) or column.name
if is_camelized:
_[camelize(key)] = getattr(self, key, None)
else:
_[key] = getattr(self, key, None)
else:
_ = self.to_dict()
return _
@classmethod
def get_list(cls, query, paging=None, fields=None):
if fields:
query = query.with_entities(*fields.values())
if paging:
page = query.paginate(paging['page'], paging['limit'])
paging['total'] = page.total
result = page.items
else:
result = query.all()
if fields:
columns = fields.keys()
result = [dict(zip(columns, _)) for _ in result]
else:
if cls._sensitive_columns: # 数据脱敏
result = [_.to_insensitive_dict() for _ in result]
else:
result = [_.to_dict() for _ in result]
if paging:
return result, paging
return result

View File

@@ -0,0 +1,30 @@
from datetime import datetime
from sqlalchemy import Column, String, DateTime
class OperationTrackMixin:
update_user_id = Column('update_user_id', String(64), comment='最后更新人id')
update_user_name = Column('update_user_name', String(64), comment='最后更新人名称')
update_time = Column('update_time', DateTime, default=datetime.now, comment='最后更新时间')
create_user_id = Column('create_user_id', String(64), comment='创建人id')
create_user_name = Column('create_user_name', String(64), comment='创建人名称')
create_time = Column('create_time', DateTime, default=datetime.now, comment='创建时间')
delete_user_id = Column('delete_user_id', String(64), comment='删除人id')
delete_user_name = Column('delete_user_name', String(64), comment='删除人名称')
delete_time = Column('delete_time', DateTime, comment='删除时间')
def track_delete(self, user_id, user_name=None):
self.delete_user_id = user_id
self.delete_user_name = user_name
self.delete_time = datetime.now()
def track_create(self, user_id, user_name=None):
self.create_user_id = user_id
self.create_user_name = user_name
self.create_time = datetime.now()
def track_update(self, user_id, user_name=None):
self.update_user_id = user_id
self.update_user_name = user_name
self.update_time = datetime.now()

View File

@@ -0,0 +1,25 @@
class SteelMixin(CalculatorMixin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@classmethod
def get_by_key(cls, name, spec, material, source, date):
spec = spec or ''
material = material or ''
source = source or ''
query = cls.query
query = query.filter(cls.name == name).filter(cls.spec == spec).filter(cls.material == material)
query = query.filter(cls.source == source).filter(cls.date == date)
return query.one_or_none()
def upsert(self):
result = self.get_by_key(self.name, self.spec, self.material, self.source, self.date)
if not result:
session = db.session
session.add(self)
session.commit()
else:
session = db.session
self.id = result.id
session.add(result)
session.commit()

View File

@@ -0,0 +1,6 @@
from commons.models import BaseModel
from core.extensions import db
class Model(BaseModel):
_db = db

48
web/commons/models/oil.py Normal file
View File

@@ -0,0 +1,48 @@
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint
from commons.models.mixin.calculator import CalculatorMixin
from commons.models.model import Model
from core.extensions import db
class Oil(db.Model, Model, CalculatorMixin):
__tablename__ = 'OIL'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, date, name='Idx_key'),
{'comment': '成品油'},
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@classmethod
def get_items(cls, year, month, name_in):
query = cls.query
query = cls.query_by_month(query, year, month)
query = query.filter(cls.name.in_(name_in))
query = query.order_by(cls.date)
result = query.all()
return result
@classmethod
def get_by_key(cls, name, date):
query = cls.query
query = query.filter(cls.name == name).filter(cls.date == date)
return query.one_or_none()
def upsert(self):
result = self.get_by_key(self.name, self.date)
if not result:
session = db.session
session.add(self)
session.commit()
else:
session = db.session
self.id = result.id
session.add(result)
session.commit()

View File

@@ -0,0 +1,81 @@
import datetime
from dateutil.relativedelta import relativedelta
from sqlalchemy import Column, Integer, String, Numeric
from commons.models.mixin.base import BaseModelMixin
from commons.models.mixin.operation_track import OperationTrackMixin
from core.extensions import db
class PricePublish(db.Model, OperationTrackMixin, BaseModelMixin):
id = Column('ID', Integer, primary_key=True)
year = Column('YEAR', Integer, default='', comment='统计年份')
month = Column('MONTH', Integer, default='', comment='统计月份')
material_id = Column('MATERIAL_ID', String(128), default='', comment='编号')
name = Column('NAME', String(128), default='', comment='材料名称')
spec = Column('SPEC', String(128), default='', comment='规格')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
price_fuzhou = Column('PRICE_FUZHOU', Numeric(16, 4), default=0, comment='福州价格')
price_xiamen = Column('PRICE_XIAMEN', Numeric(16, 4), default=0, comment='厦门价格')
price_putian = Column('PRICE_PUTIAN', Numeric(16, 4), default=0, comment='莆田价格')
price_sanming = Column('PRICE_SANMING', Numeric(16, 4), default=0, comment='三明价格')
price_quanzhou = Column('PRICE_QUANZHOU', Numeric(16, 4), default=0, comment='泉州价格')
price_zhangzhou = Column('PRICE_ZHANGZHOU', Numeric(16, 4), default=0, comment='漳州价格')
price_nanpin = Column('PRICE_NANPIN', Numeric(16, 4), default=0, comment='南平价格')
price_longyan = Column('PRICE_LONGYAN', Numeric(16, 4), default=0, comment='龙岩价格')
price_ningde = Column('PRICE_NINGDE', Numeric(16, 4), default=0, comment='宁德价格')
price_pintan = Column('PRICE_PINTAN', Numeric(16, 4), default=0, comment='平潭价格')
tax = Column('TAX', Numeric(4, 2), default=0, comment='税率')
status = Column('STATUS', Integer, default=0, comment='状态')
type = Column('TYPE', Integer, default=0, comment='类型')
unit = Column('UNIT', String(128), default='', comment='单位')
__tablename__ = 'PRICE_PUBLISH'
__table_args__ = (
{'comment': '发布价格'},
)
@classmethod
def get_by_key(cls, name, year, month, type):
query = cls.query
query = query.filter(cls.name == name).filter(cls.year == year).filter(cls.month == month).filter(
cls.type == type)
return query.one_or_none()
def find_by_key(self):
cls = self.__class__
query = cls.query
query = query.filter(cls.year == self.year)
query = query.filter(cls.month == self.month)
query = query.filter(cls.name == self.name)
query = query.filter(cls.type == self.type)
result = query.one_or_none()
return result
# @classmethod
# def query_previous_month(cls, query, start_date: datetime.date, count=6):
# end_date = start_date + relativedelta(months=1)
# query = query.filter(cls.date >= end_date - relativedelta(months=count))
# query = query.filter(cls.date < end_date)
# return query
@classmethod
def query_previous_month(cls, query, start_date: datetime.date, count=6):
condition = False
for i in range(count):
date = start_date - relativedelta(months=i)
condition = condition or (cls.year == date.year and cls.month == date.month)
query.filter(condition)
return query
@classmethod
def get_query(cls, year=None, month=None, name_in=None):
query = cls.query
if year:
query = query.filter(cls.year == year)
if month:
query = query.filter(cls.month == month)
if name_in:
query = query.filter(cls.name.in_(name_in))
return query

View File

@@ -0,0 +1,60 @@
from sqlalchemy import Column, Integer, String, Numeric
from commons.models.mixin.base import BaseModelMixin
from commons.models.mixin.operation_track import OperationTrackMixin
from core.extensions import db
class PriceResult(db.Model, OperationTrackMixin, BaseModelMixin):
id = Column('ID', Integer, primary_key=True)
material_id = Column('MATERIAL_ID', String(128), default='', comment='编号')
name = Column('NAME', String(128), default='', comment='材料名称')
year = Column('YEAR', Integer, default='', comment='统计年份')
month = Column('MONTH', Integer, default='', comment='统计月份')
price_ftb = Column('PRICE_FTB', Numeric(16, 4), default=0, comment='福州交通局价格')
fluctuating_ftb = Column('FLUCTUATING_FTB', Numeric(16, 4), default=0, comment='福州交通局浮动')
price_ss = Column('PRICE_SS', Numeric(16, 4), default=0, comment='三明钢铁价格')
fluctuating_ss = Column('FLUCTUATING_SS', Numeric(16, 4), default=0, comment='三明钢铁浮动')
price_fhb = Column('PRICE_FHB', Numeric(16, 4), default=0, comment='福州公路局价格')
fluctuating_fhb = Column('FLUCTUATING_FHB', Numeric(16, 4), default=0, comment='福州公路局浮动')
price_network = Column('PRICE_NETWORK', Numeric(16, 4), default=0, comment='网络价格')
fluctuating_network = Column('FLUCTUATING_NETWORK', Numeric(16, 4), default=0, comment='网络浮动')
price_survey = Column('PRICE_SURVEY', Numeric(16, 4), default=0, comment='调查价格')
fluctuating_survey = Column('FLUCTUATING_SURVEY', Numeric(16, 4), default=0, comment='调查浮动')
price_last_month = Column('PRICE_LAST_MONTH', Numeric(16, 4), default=0, comment='上月发布价格')
price_calculate = Column('PRICE_CALCULATE', Numeric(16, 4), default=0, comment='计算价格')
price_recommend = Column('PRICE_RECOMMEND', Numeric(16, 4), default=0, comment='推荐价格')
fluctuating_recommend = Column('FLUCTUATING_RECOMMEND', Numeric(16, 4), default=0, comment='推荐浮动')
spec = Column('SPEC', String(128), default='', comment='规格')
unit = Column('UNIT', String(128), default='', comment='单位')
__tablename__ = 'PRICE_RESULT'
__table_args__ = (
{'comment': '计算结果'},
)
@classmethod
def get_by_key(cls, name, year, month):
query = cls.query
query = query.filter(cls.name == name).filter(cls.year == year).filter(cls.month == month)
return query.one_or_none()
def find_by_key(self):
cls = self.__class__
query = cls.query
query = query.filter(cls.year == self.year)
query = query.filter(cls.month == self.month)
query = query.filter(cls.name == self.name)
result = query.one_or_none()
return result
@classmethod
def get_query(cls, year, month, name_in=None, name=None):
query = cls.query
query = query.filter(cls.year == year)
query = query.filter(cls.month == month)
if name_in:
query = query.filter(cls.name.in_(name_in))
if name:
query = query.filter(cls.name == name)
return query

View File

@@ -0,0 +1,35 @@
import datetime
from dateutil.relativedelta import relativedelta
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint
from core.extensions import db
class SanmingSteel(db.Model):
__tablename__ = 'SANMING_STEEL'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
material = Column('MATERIAL', String(64), default='', comment='材质')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
fluctuating = Column('FLUCTUATING', Numeric(16, 4), default=0, comment='浮动')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, spec, material, date, name='Idx_key'),
{'comment': '三明钢铁'},
)
@classmethod
def get_query(cls, year, month, name, spec):
start_date = datetime.date(year, month, 1)
end_date = start_date + relativedelta(months=1)
query = cls.query
query = query.filter(cls.date >= start_date)
query = query.filter(cls.date < end_date)
if name:
query = query.filter(cls.name == name)
if spec:
query = query.filter(cls.spec == spec)
return query

View File

@@ -0,0 +1,33 @@
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint, func
from commons.models.mixin.steel import SteelMixin
from core.extensions import db
class SteelPlate(db.Model, SteelMixin):
__tablename__ = 'STEEL_PLATE'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
material = Column('MATERIAL', String(64), default='', comment='材质')
source = Column('SOURCE', String(64), default='', comment='产地')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
fluctuating = Column('FLUCTUATING', Numeric(16, 4), default=0, comment='浮动')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, spec, material, source, date, name='Idx_key'),
{'comment': '中厚板'},
)
@classmethod
def get_items(cls, year, month, spec_in=('12', '16-20', '22-28'), source_in=('三钢闽光',), name_in=('普中板', '工字钢')):
query = cls.query
query = cls.query_by_month(query, year, month)
query = query.filter(cls.spec.in_(spec_in))
query = query.filter(cls.source.in_(source_in))
query = query.filter(cls.name.in_(name_in))
query = query.with_entities(cls.spec, func.avg(cls.price))
query = query.group_by(cls.spec)
result = query.all()
return result

View File

@@ -0,0 +1,44 @@
import datetime
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint, func
from calculators import Helper
from commons.models.mixin.steel import SteelMixin
from core.extensions import db
class SteelRebar(db.Model, SteelMixin):
__tablename__ = 'STEEL_REBAR'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
material = Column('MATERIAL', String(64), default='', comment='材质')
source = Column('SOURCE', String(64), default='', comment='产地')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
fluctuating = Column('FLUCTUATING', Numeric(16, 4), default=0, comment='浮动')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, spec, material, source, date, name='Idx_key'),
{'comment': '钢筋'},
)
@classmethod
def query_by_month(cls, query, year, month):
last_month_year, last_month = Helper.get_last_month(year, month)
query = query.filter(cls.date >= datetime.date(last_month_year, last_month, 26))
query = query.filter(cls.date <= datetime.date(year, month, 25))
return query
@classmethod
def get_items(cls, year, month, material, source='三钢闽光', name_in=('高线', '螺纹钢')):
query = cls.query
query = cls.query_by_month(query, year, month)
query = query.filter(cls.material == material)
query = query.filter(cls.source == source)
query = query.filter(cls.name.in_(name_in))
query = query.with_entities(cls.spec, cls.material, func.avg(cls.price))
query = query.group_by(cls.spec, cls.material)
result = query.all()
return result

View File

@@ -0,0 +1,32 @@
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint, func
from commons.models.mixin.steel import SteelMixin
from core.extensions import db
class SteelSection(db.Model, SteelMixin):
__tablename__ = 'STEEL_SECTION'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
material = Column('MATERIAL', String(64), default='', comment='材质')
source = Column('SOURCE', String(64), default='', comment='产地')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
fluctuating = Column('FLUCTUATING', Numeric(16, 4), default=0, comment='浮动')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, spec, material, source, date, name='Idx_key'),
{'comment': '型钢'},
)
@classmethod
def get_items(cls, year, month, spec_in=('140*140*12', '25#'), source_in=('唐山弘泰', '唐山正丰'), name_in=('角钢', '工字钢')):
query = cls.query
query = cls.query_by_month(query, year, month)
query = query.filter(cls.spec.in_(spec_in))
query = query.filter(cls.source.in_(source_in))
query = query.filter(cls.name.in_(name_in))
query = query.with_entities(func.avg(cls.price))
result = query.all()
return result

View File

@@ -0,0 +1,32 @@
from sqlalchemy import Column, Integer, String, Numeric, Date, UniqueConstraint, func
from commons.models.mixin.steel import SteelMixin
from core.extensions import db
class SteelStrand(db.Model, SteelMixin):
__tablename__ = 'STEEL_STRAND'
id = Column('ID', Integer, primary_key=True)
name = Column('NAME', String(128), default='', comment='名称')
spec = Column('SPEC', String(128), default='', comment='规格')
material = Column('MATERIAL', String(64), default='', comment='材质')
source = Column('SOURCE', String(64), default='', comment='产地')
price = Column('PRICE', Numeric(16, 4), default=0, comment='价格')
fluctuating = Column('FLUCTUATING', Numeric(16, 4), default=0, comment='浮动')
date = Column('DATE', Date, comment='日期')
__table_args__ = (
UniqueConstraint(name, spec, material, source, date, name='Idx_key'),
{'comment': '钢绞线'},
)
@classmethod
def get_items(cls, year, month, material_in=('SWRH82B',), name_in=('弹簧钢',)):
query = cls.query
query = cls.query_by_month(query, year, month)
query = query.filter(cls.material.in_(material_in))
query = query.filter(cls.name.in_(name_in))
query = query.with_entities(cls.material, func.avg(cls.price))
query = query.group_by(cls.material)
result = query.all()
return result