Compare commits
10 Commits
cba5738557
...
c4c74cda65
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c4c74cda65 | ||
![]() |
80272d2bf3 | ||
![]() |
1402b1a1e3 | ||
![]() |
d752fe17c8 | ||
![]() |
463f9256fa | ||
![]() |
a10ab91a31 | ||
![]() |
7a9aa93a10 | ||
![]() |
40c1593ff7 | ||
![]() |
6ada6371a3 | ||
![]() |
bfb1315028 |
48
.gitea/workflows/ci.yaml
Normal file
48
.gitea/workflows/ci.yaml
Normal file
@@ -0,0 +1,48 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- test
|
||||
|
||||
env:
|
||||
DEPLOY_PATH: /home/opt/app/material-api
|
||||
DEPLOY_TEST_HOST_IP: 172.17.0.1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latests
|
||||
container:
|
||||
image: python:3.7.16
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
run: |
|
||||
git clone --depth 1 "http://test:89085111dd6939710a992d6404bd61a50e420685@8.138.239.222:20300/${GITHUB_REPOSITORY}.git" .
|
||||
git checkout "${GITHUB_SHA}"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir dist
|
||||
PYTHONUSERBASE=$CI_PROJECT_DIR/home pip install --upgrade pip -i https://mirror.aliyun.com/pypi/simple --user
|
||||
PYTHONUSERBASE=$CI_PROJECT_DIR/home pip install -r ./requirements.txt -i https://mirror.aliyun.com/pypi/simple --user
|
||||
rsync -ha ./ ./dist --exclude=dist --exclude=.git --delete
|
||||
|
||||
- name: Deploy
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
echo "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
|
||||
echo "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
ssh -o StrictHostKeyChecking=no root@$DEPLOY_TEST_HOST_IP "mkdir -p $DEPLOY_PATH"
|
||||
|
||||
rsync -r ./dist/ ${DEPLOY_DEV_HOST_IP}:${DEPLOY_PATH} --delete
|
||||
ssh ${SSH_OPTS} ${DEPLOY_DEV_HOST_IP} "cd ${DEPLOY_PATH} && source /etc/profile && docker-compose up -d --force-recreate"
|
||||
|
||||
ssh root@$DEPLOY_TEST_HOST_IP "rm -f $DEPLOY_PATH/*.jar"
|
||||
scp ruoyi-admin/target/ruoyi-admin.jar root@$DEPLOY_TEST_HOST_IP:$DEPLOY_PATH/
|
||||
ssh root@$DEPLOY_TEST_HOST_IP "mv $DEPLOY_PATH/ruoyi-admin.jar $DEPLOY_PATH/app.jar"
|
||||
scp docker-compose.test.yml root@$DEPLOY_TEST_HOST_IP:$DEPLOY_PATH/
|
||||
ssh root@$DEPLOY_TEST_HOST_IP "mv $DEPLOY_PATH/docker-compose.test.yml $DEPLOY_PATH/docker-compose.yml"
|
||||
ssh root@$DEPLOY_TEST_HOST_IP "cd $DEPLOY_PATH && docker compose up -d --force-recreate"
|
@@ -38,6 +38,7 @@ def refresh_task(task_id):
|
||||
class CalculateQuery(BaseModel):
|
||||
year: int = Field(title='年份')
|
||||
month: int = Field(title='月份')
|
||||
only_avg: int = Field(title='是否只计算均值', default=0)
|
||||
|
||||
|
||||
@data.route('/calculate', methods=['GET'])
|
||||
@@ -51,6 +52,6 @@ def start_calculate(query: CalculateQuery):
|
||||
@data.route('/collect', methods=['GET'])
|
||||
@siwa.doc(tags=[""], summary='触发计算任务', query=CalculateQuery)
|
||||
def start_collect(query: CalculateQuery):
|
||||
collect(year=query.year, month=query.month)
|
||||
collect(year=query.year, month=query.month, only_avg=query.only_avg)
|
||||
|
||||
return Response()
|
||||
|
@@ -1,4 +1,4 @@
|
||||
from decimal import Decimal
|
||||
from decimal import Decimal, ROUND_HALF_UP
|
||||
|
||||
from commons.models.data_fujian import DataFujian
|
||||
from commons.models.data_network import DataNetwork
|
||||
@@ -37,7 +37,8 @@ class Helper:
|
||||
class RoundMethod:
|
||||
@staticmethod
|
||||
def normal(n, round_bit):
|
||||
result = round(n, round_bit)
|
||||
q_ext = Decimal('0.' + '0' * round_bit)
|
||||
result = Decimal(n).quantize(q_ext, rounding=ROUND_HALF_UP)
|
||||
return result if round_bit != 0 else int(result)
|
||||
|
||||
@staticmethod
|
||||
@@ -133,6 +134,7 @@ class Calculator:
|
||||
}
|
||||
|
||||
def run(self):
|
||||
self._get_weight()
|
||||
self.price_ftb, self.fluctuating_ftb = self._get_ftb_price()
|
||||
self.price_ss, self.fluctuating_ss = self._get_ss_price()
|
||||
self.price_fhb, self.fluctuating_fhb = self._get_fhb_price()
|
||||
@@ -190,17 +192,20 @@ class Calculator:
|
||||
return getattr(self.previous_prices, 'price_recommend', 0)
|
||||
|
||||
def _get_calculate_price(self, round_dit=2):
|
||||
prices = (self.price_ftb, self.price_ss, self.price_fhb, self.price_network, self.price_survey, self.price_last_month)
|
||||
total = sum(float(i) for i in prices)
|
||||
if total == 0:
|
||||
prices = [
|
||||
self.price_ftb * self.weight_ftb,
|
||||
self.price_ss * self.weight_ss,
|
||||
self.price_fhb * self.weight_fhb,
|
||||
self.price_network * self.weight_network,
|
||||
self.price_survey * self.weight_survey,
|
||||
]
|
||||
if sum(prices) == 0:
|
||||
return 0
|
||||
result = total / len([i for i in prices if i != 0])
|
||||
result = round(result, round_dit)
|
||||
result = sum(prices) / sum([self.weight_ftb, self.weight_ss, self.weight_fhb, self.weight_network, self.weight_survey])
|
||||
result = self.round_method(result, self.round_bit)
|
||||
return result
|
||||
|
||||
def _get_recommend_price(self, round_by=10):
|
||||
self._get_weight()
|
||||
|
||||
if not self.previous_prices:
|
||||
return 0, 0
|
||||
|
||||
@@ -226,7 +231,7 @@ class Calculator:
|
||||
|
||||
def _get_weight(self):
|
||||
# 如果有上月数据按上月权重计算 无则平均数
|
||||
if self._previous_prices:
|
||||
if self.previous_prices:
|
||||
self.weight_ftb = self._previous_prices.weight_ftb
|
||||
self.weight_ss = self._previous_prices.weight_ss
|
||||
self.weight_fhb = self._previous_prices.weight_fhb
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import datetime
|
||||
import decimal
|
||||
from decimal import Decimal
|
||||
|
||||
from sqlalchemy import func
|
||||
|
||||
from calculators import Helper
|
||||
from commons.models.fujian_survey import FujianSurvey
|
||||
from commons.models.price_publish import PricePublish
|
||||
from commons.models.price_result import PriceResult
|
||||
from commons.models.material import Material
|
||||
@@ -11,7 +12,8 @@ from commons.models.material import Material
|
||||
|
||||
class Collector:
|
||||
|
||||
def __init__(self, year, month, force=True):
|
||||
def __init__(self, year, month, force=True, only_avg=0):
|
||||
self.only_avg = only_avg
|
||||
self.year = year
|
||||
self.month = month
|
||||
self.force = True # todo-2 已发布的价格不在覆盖计算
|
||||
@@ -21,14 +23,17 @@ class Collector:
|
||||
self.material_codes = [m.code for m in self.materials if m.code]
|
||||
# 缓存材料税率信息
|
||||
self.tax_map = {m.code: m.tax for m in self.materials if m.code}
|
||||
self.unit_map = {m.code: m.unit for m in self.materials if m.code}
|
||||
self.name_map = {m.code: m.name for m in self.materials if m.code}
|
||||
self.spec_map = {m.code: m.spec for m in self.materials if m.code}
|
||||
self.round_bit_map = {m.code: m.round_bit for m in self.materials if m.code}
|
||||
|
||||
def get_avg(self):
|
||||
query = PricePublish.get_query(material_id_in=self.material_codes)
|
||||
query = PricePublish.query_previous_month(query, start_date=datetime.date(self.year, self.month, 1), count=6)
|
||||
query = query.filter(PricePublish.type == '1')
|
||||
query = query.with_entities(
|
||||
PricePublish.material_id,
|
||||
PricePublish.name,
|
||||
PricePublish.spec,
|
||||
func.avg(PricePublish.price),
|
||||
func.avg(PricePublish.price_fuzhou),
|
||||
func.avg(PricePublish.price_xiamen),
|
||||
@@ -41,43 +46,39 @@ class Collector:
|
||||
func.avg(PricePublish.price_ningde),
|
||||
func.avg(PricePublish.price_pintan),
|
||||
func.avg(PricePublish.price_zhangzhoukfq),
|
||||
PricePublish.tax,
|
||||
PricePublish.unit,
|
||||
)
|
||||
query = query.filter(PricePublish.price != 0)
|
||||
query = query.group_by(
|
||||
PricePublish.material_id,
|
||||
PricePublish.name,
|
||||
PricePublish.spec,
|
||||
PricePublish.tax,
|
||||
PricePublish.unit,
|
||||
)
|
||||
data = query.all()
|
||||
for item in data:
|
||||
material_id, name, spec, price, price_fuzhou, price_xiamen, price_putian, price_sanming, price_quanzhou, \
|
||||
price_zhangzhou, price_nanpin, price_longyan, price_ningde, price_pintan, price_zhangzhoukfq, tax, unit, = item
|
||||
material_id, price, price_fuzhou, price_xiamen, price_putian, price_sanming, price_quanzhou, \
|
||||
price_zhangzhou, price_nanpin, price_longyan, price_ningde, price_pintan, price_zhangzhoukfq = item
|
||||
display_digit = self.digit_map.get(material_id, 1)
|
||||
round_bit = self.round_bit_map.get(material_id, 2)
|
||||
q_ext = Decimal('0.' + '0' * round_bit)
|
||||
PricePublish(
|
||||
year=self.year,
|
||||
month=self.month,
|
||||
material_id=material_id,
|
||||
name=name,
|
||||
spec=spec,
|
||||
price=round(price, 2),
|
||||
price_fuzhou=round(price_fuzhou or 0, 2),
|
||||
price_xiamen=round(price_xiamen or 0, 2),
|
||||
price_putian=round(price_putian or 0, 2),
|
||||
price_sanming=round(price_sanming or 0, 2),
|
||||
price_quanzhou=round(price_quanzhou or 0, 2),
|
||||
price_zhangzhou=round(price_zhangzhou or 0, 2),
|
||||
price_nanpin=round(price_nanpin or 0, 2),
|
||||
price_longyan=round(price_longyan or 0, 2),
|
||||
price_ningde=round(price_ningde or 0, 2),
|
||||
price_pintan=round(price_pintan or 0, 2),
|
||||
price_zhangzhoukfq=round(price_zhangzhoukfq or 0, 2),
|
||||
tax=self.tax_map.get(material_id, tax), # 从材料表获取税率
|
||||
name=self.name_map.get(material_id, ''),
|
||||
spec=self.spec_map.get(material_id, ''),
|
||||
price=price.quantize(q_ext, decimal.ROUND_HALF_UP) if price else 0,
|
||||
price_fuzhou=price_fuzhou.quantize(q_ext, decimal.ROUND_HALF_UP) if price_fuzhou else 0,
|
||||
price_xiamen=price_xiamen.quantize(q_ext, decimal.ROUND_HALF_UP) if price_xiamen else 0,
|
||||
price_putian=price_putian.quantize(q_ext, decimal.ROUND_HALF_UP) if price_putian else 0,
|
||||
price_sanming=price_sanming.quantize(q_ext, decimal.ROUND_HALF_UP) if price_sanming else 0,
|
||||
price_quanzhou=price_quanzhou.quantize(q_ext, decimal.ROUND_HALF_UP) if price_quanzhou else 0,
|
||||
price_zhangzhou=price_zhangzhou.quantize(q_ext, decimal.ROUND_HALF_UP) if price_zhangzhou else 0,
|
||||
price_nanpin=price_nanpin.quantize(q_ext, decimal.ROUND_HALF_UP) if price_nanpin else 0,
|
||||
price_longyan=price_longyan.quantize(q_ext, decimal.ROUND_HALF_UP) if price_longyan else 0,
|
||||
price_ningde=price_ningde.quantize(q_ext, decimal.ROUND_HALF_UP) if price_ningde else 0,
|
||||
price_pintan=price_pintan.quantize(q_ext, decimal.ROUND_HALF_UP) if price_pintan else 0,
|
||||
price_zhangzhoukfq=price_zhangzhoukfq.quantize(q_ext, decimal.ROUND_HALF_UP) if price_zhangzhoukfq else 0,
|
||||
tax=self.tax_map.get(material_id, 0), # 从材料表获取税率
|
||||
type=2,
|
||||
unit=unit,
|
||||
unit=self.unit_map.get(material_id, ''),
|
||||
display_digit=display_digit,
|
||||
).upsert()
|
||||
|
||||
@@ -120,9 +121,11 @@ class Collector:
|
||||
|
||||
def run(self):
|
||||
# 当月价
|
||||
# self.get_from_survey()
|
||||
self.get_from_result()
|
||||
if not self.only_avg:
|
||||
PricePublish.clean(self.year, self.month, type=1) # 清空当月价
|
||||
self.get_from_result()
|
||||
# 近半年平均价
|
||||
PricePublish.clean(self.year, self.month, type=2) # 清空近半年平均价
|
||||
self.get_avg()
|
||||
|
||||
|
||||
|
@@ -6,6 +6,12 @@ class BaseModelMixin:
|
||||
def upsert(self):
|
||||
result = self.find_by_key()
|
||||
session = self._db.session
|
||||
# # 住建厅数据初始化
|
||||
# if result:
|
||||
# result.price_fujian = self.price_fujian
|
||||
# result.fluctuating_fujian = self.fluctuating_fujian
|
||||
# session.add(result)
|
||||
# session.commit()
|
||||
if result:
|
||||
session.delete(result)
|
||||
session.flush()
|
||||
|
@@ -1,7 +1,8 @@
|
||||
import datetime
|
||||
from operator import and_
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from sqlalchemy import Column, Integer, String, Numeric
|
||||
from sqlalchemy import Column, Integer, String, Numeric, or_
|
||||
|
||||
from commons.models.mixin.base import BaseModelMixin
|
||||
from commons.models.mixin.operation_track import OperationTrackMixin
|
||||
@@ -40,8 +41,11 @@ class PricePublish(db.Model, Model, OperationTrackMixin, BaseModelMixin):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def clean(cls, year, month):
|
||||
cls.query.filter(cls.year == year, cls.month == month).delete()
|
||||
def clean(cls, year, month, type=None):
|
||||
query = cls.query.filter(cls.year == year, cls.month == month)
|
||||
if type:
|
||||
query.filter(cls.type == type)
|
||||
query.delete()
|
||||
|
||||
@classmethod
|
||||
def get_by_key(cls, name, year, month, type):
|
||||
@@ -71,10 +75,10 @@ class PricePublish(db.Model, Model, OperationTrackMixin, BaseModelMixin):
|
||||
@classmethod
|
||||
def query_previous_month(cls, query, start_date: datetime.date, count=6):
|
||||
condition = False
|
||||
for i in range(count):
|
||||
for i in range(0, count):
|
||||
date = start_date - relativedelta(months=i)
|
||||
condition = condition or (cls.year == date.year and cls.month == date.month)
|
||||
query.filter(condition)
|
||||
condition = or_(condition, and_(cls.year == str(date.year), cls.month == str(date.month)))
|
||||
query = query.filter(condition)
|
||||
return query
|
||||
|
||||
@classmethod
|
||||
|
@@ -18,7 +18,7 @@ def calculate(year=2023, month=8):
|
||||
calculator.material_id = material.id
|
||||
calculator.unit = material.unit
|
||||
calculator.spec = material.spec
|
||||
|
||||
|
||||
# 设置小数位数,如果数据库中未设置则使用默认值0
|
||||
calculator.round_bit = material.round_bit if material.round_bit is not None else 0
|
||||
|
||||
@@ -39,11 +39,11 @@ if __name__ == '__main__':
|
||||
from core.factory import ClientApp
|
||||
|
||||
with ClientApp().app_context():
|
||||
calculate(2024, 4)
|
||||
calculate(2025, 5)
|
||||
|
||||
# for i in range(2, 12):
|
||||
# calculate(2022, i+1)
|
||||
# for i in range(0, 12):
|
||||
# calculate(2023, i+1)
|
||||
# for i in range(1, 5+1):
|
||||
# calculate(2025, i)
|
||||
# for i in range(6-1, 10):
|
||||
# calculate(2024, i+1)
|
||||
|
@@ -2,12 +2,11 @@ from collectors import Collector
|
||||
from commons.models.price_publish import PricePublish
|
||||
|
||||
|
||||
def collect(year=2023, month=11):
|
||||
def collect(year=2023, month=11, only_avg=0):
|
||||
"""
|
||||
整理发布价格
|
||||
"""
|
||||
PricePublish.clean(year, month) # 清空当月数据
|
||||
collector = Collector(year, month)
|
||||
collector = Collector(year, month, only_avg=only_avg)
|
||||
collector.run()
|
||||
|
||||
|
||||
@@ -15,11 +14,11 @@ if __name__ == '__main__':
|
||||
from core.factory import ClientApp
|
||||
|
||||
with ClientApp().app_context():
|
||||
collect(2023, 3)
|
||||
collect(2025, 5)
|
||||
|
||||
# for i in range(2, 12):
|
||||
# collect(2022, i + 1)
|
||||
# for i in range(0, 12):
|
||||
# for i in range(4):
|
||||
# collect(2025, i + 1)
|
||||
# for i in range(9,12):
|
||||
# collect(2023, i + 1)
|
||||
# for i in range(5, 10):
|
||||
# for i in range(12):
|
||||
# collect(2024, i + 1)
|
||||
|
Reference in New Issue
Block a user