import datetime import json import uuid from uuid import UUID import requests from fastapi import HTTPException from app.config import TaskEnv from app.models.project import ProjectModel, UpdateSts, ProjectSts, Design, ProjectStatusAgreement from core.repositories.base import BaseRepository from core.service.mongo_db import use_collection from core.utils.table_engine import TableEngineRequestType, TableEngineExport from core.utils.te import NewTableEngine from typing import TypeVar, List COLLECTION = "project" T = TypeVar('T') class ProjectRepository(BaseRepository[ProjectModel]): def __init__(self): super().__init__(collection=COLLECTION, model=ProjectModel) def create_code(self, coding: ProjectModel): code = str(coding.counter) print("code1", code) if len(code) < 4: code = code.rjust(4, '0') print("code2", code) code = coding.design.nature + coding.design.type + code return code async def create_report_price(self, _inp: ProjectModel): if _inp.monitor and _inp.monitor.detail and _inp.monitor.detail.first_amount: price = { '_id': uuid.uuid4(), 'project_id': _inp.id, 'first_amount': _inp.monitor.detail.first_amount } await use_collection(TaskEnv.CLN_PROJECT_PRICE_REPORT).insert_one(price) return True async def update_report_price(self, update: ProjectModel): if update.monitor and update.monitor.detail and update.monitor.detail.first_amount: price = await use_collection(TaskEnv.CLN_PROJECT_PRICE_REPORT).find_one({'project_id': update.id}) if not price: price = { '_id': uuid.uuid4(), 'project_id': update.id, 'first_amount': update.monitor.detail.first_amount } await use_collection(TaskEnv.CLN_PROJECT_PRICE_REPORT).insert_one(price) else: await use_collection(TaskEnv.CLN_PROJECT_PRICE_REPORT).update_one({'project_id': update.id}, { '$set': {'first_amount': update.monitor.detail.first_amount}}) return True def creat_date_delay(self, coding: ProjectModel): start_date = coding.monitor.detail.date_create_project first_time_months = int(coding.monitor.detail.first_time) new_month = start_date.month + first_time_months new_year = start_date.year + (new_month - 1) // 12 new_month = (new_month - 1) % 12 + 1 return start_date.replace(year=new_year, month=new_month) async def create(self, coding: ProjectModel): coding.counter = 1 last_project = await use_collection(COLLECTION).find({}).sort("$natural", -1).to_list(None) if last_project: coding.counter = last_project[0]["counter"] + 1 code = self.create_code(coding) coding.design.code = 'D' + code coding.init_id().cu_at() if coding.monitor: coding.monitor.code = 'S' + code coding.has_monitor = True await self.create_report_price(coding) if coding.monitor.detail.date_create_project and coding.monitor.detail.first_time: coding.date_delay = self.creat_date_delay(coding) else: coding.has_monitor = False await use_collection(COLLECTION).insert_one(coding.mongo_dict()) if coding.design.status_agreement: _model = ProjectStatusAgreement( project_id=coding.id, status=coding.design.status_agreement ).init_id().cu_at() await use_collection(TaskEnv.CLN_PROJECT_AGREEMENT).insert_one(_model.mongo_dict()) return await self.get(coding.id) async def update(self, _id: UUID, update: ProjectModel): old_project_dict = await use_collection(COLLECTION).find_one({"_id": _id}) old_project = ProjectModel(**old_project_dict) if update.monitor and not old_project.monitor: code = self.create_code(update) update.monitor.code = 'S' + code if update.design.nature != old_project.design.nature or update.design.type != old_project.design.type: code = self.create_code(update) update.design.code = 'D' + code if update.monitor: update.monitor.code = 'S' + code if update.monitor: update.has_monitor = True await self.update_report_price(update) old_detail = old_project_dict.get("monitor", {}).get("detail", {}) old_date = old_detail.get("date_create_project") old_first_time = old_detail.get("first_time") update_dict = update.mongo_dict() new_detail = update_dict.get("monitor", {}).get("detail", {}) new_date = new_detail.get("date_create_project") new_first_time = new_detail.get("first_time") can_calculate = (new_date is not None and new_first_time is not None) if can_calculate and ((old_date is None or new_date != old_date)or(old_first_time is None or new_first_time != old_first_time)): update.date_delay = self.creat_date_delay(update) + datetime.timedelta(days=update.all_delay_day) update.u_at() await use_collection(COLLECTION).update_one({"_id": _id}, {"$set": update.mongo_dict()}) if old_project.design.status_agreement != update.design.status_agreement: _model = ProjectStatusAgreement( project_id=_id, status=update.design.status_agreement ).init_id().cu_at() await use_collection(TaskEnv.CLN_PROJECT_AGREEMENT).insert_one(_model.mongo_dict()) return await self.get(_id) async def update_design_sts(self, _id: UUID, update: UpdateSts): old_project = await use_collection(COLLECTION).find_one({"_id": _id}) if not old_project: raise HTTPException(status_code=400, detail='این پروژه وجود ندارد') await use_collection(COLLECTION).update_one({"_id": _id}, {"$set": { 'design.sts': update.sts, 'design.reason_stop': update.reason_stop }}) sts_class = ProjectSts( project_id=_id, type='design', sts=update.sts, description=update.reason_stop ).init_id().cu_at() await use_collection(TaskEnv.CLN_PROJECT_STS).insert_one(sts_class.mongo_dict()) return await self.get(_id) async def update_monitor_sts(self, _id: UUID, update: UpdateSts): old_project = await use_collection(COLLECTION).find_one({"_id": _id}) if not old_project: raise HTTPException(status_code=400, detail='این پروژه وجود ندارد') await use_collection(COLLECTION).update_one({"_id": _id}, {"$set": { 'monitor.sts': update.sts, 'monitor.reason_sts': update.reason_stop }}) sts_class = ProjectSts( project_id=_id, type='monitor', sts=update.sts, description=update.reason_stop ).init_id().cu_at() await use_collection(TaskEnv.CLN_PROJECT_STS).insert_one(sts_class.mongo_dict()) return await self.get(_id) async def delete(self, _id: UUID): old_project = await use_collection(COLLECTION).find_one({"_id": _id}) if not old_project: raise HTTPException(status_code=400, detail='این پروژه وجود ندارد') await use_collection(COLLECTION).update_one({"_id": _id}, {"$set": { 'sts': 2, }}) return True async def restore(self, _id: UUID): old_project = await use_collection(COLLECTION).find_one({"_id": _id}) if not old_project: raise HTTPException(status_code=400, detail='این پروژه وجود ندارد') await use_collection(COLLECTION).update_one({"_id": _id}, {"$set": { 'sts': 1, }}) return True async def list_project_design(self): project = await use_collection(COLLECTION).find({'monitor': {"$exists": 0}}).to_list(None) return project async def list_project_monitor(self): project = await use_collection(COLLECTION).find({'monitor': {"$exists": 1}}).to_list(None) return project async def list_sts_design(self, _id: uuid.UUID): sts_project = await use_collection(TaskEnv.CLN_PROJECT_STS).find({ "project_id": _id, "type": "design" }).to_list(None) return sts_project async def list_sts_monitor(self, _id: uuid.UUID): sts_project = await use_collection(TaskEnv.CLN_PROJECT_STS).find({ "project_id": _id, "type": "monitor" }).to_list(None) return sts_project async def list_project(self): project = await use_collection(TaskEnv.CLN_PROJECT).find({}).to_list(None) return project async def set_sts_two_for_monitor(self, project_id: uuid.UUID): project = await use_collection(TaskEnv.CLN_PROJECT).find_one({"_id": project_id}) if not ('sts' in project['monitor'] and project['monitor']['sts'] > 1): await use_collection(TaskEnv.CLN_PROJECT).update_one( {'_id': project_id}, {"$set": {"monitor.sts": 2}}) sts_class = ProjectSts( project_id=project_id, type='monitor', sts=2 ).init_id().cu_at() await use_collection(TaskEnv.CLN_PROJECT_STS).insert_one(sts_class.mongo_dict()) return True async def getList(self, state: str='null'): if not state == 'null': projects = await use_collection(TaskEnv.CLN_PROJECT).find({"sts": 1,"design.state":state }).to_list(None) else: projects = await use_collection(TaskEnv.CLN_PROJECT).find({"sts": 1}).to_list(None) return projects async def fetch_delete(self, _input: TableEngineRequestType) -> TableEngineExport[T]: return await NewTableEngine.mongo( query_class=use_collection(self.COLLECTION), soft_deleted=True, model=self.MODEL, search_cols=['design.title'], extra_filter=[{'sts': 2}], inputs=_input.te) \ .to_dict() async def fetch(self, _input: TableEngineRequestType) -> TableEngineExport[T]: return await NewTableEngine.mongo( query_class=use_collection(self.COLLECTION), soft_deleted=True, model=self.MODEL, search_cols=['design.title'], extra_filter=[{'sts': 1}], inputs=_input.te) \ .to_dict() async def get_all(self): url = 'http://api.khanesaziceco.ir/api/api/project/table' headers = { 'authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9hcGkua2hhbmVzYXppY2Vjby5pclwvYXBpXC9hdXRoXC9sb2dpbiIsImlhdCI6MTc0OTg0NjExMSwiZXhwIjoxNzUyNDM4MTExLCJuYmYiOjE3NDk4NDYxMTEsImp0aSI6Ikh6OURsZHR2U2FVRU5rd24iLCJzdWIiOjEzNiwicHJ2IjoiMjNiZDVjODk0OWY2MDBhZGIzOWU3MDFjNDAwODcyZGI3YTU5NzZmNyJ9.C7vRTRbhKrKuoFd334imKAIYFnU-9ygCIFmrwiPGVxY'} data = {"page": 1, "limit": 400, "sort": "_id" } res = requests.post(url, data=json.dumps(data), headers=headers) a = res.json() obj = [] rows = a['rows'] rows.reverse() for i in rows: _set = ProjectModel( sts=1, counter=i['id'], design=Design(**i), created_at=i['created_at'], updated_at=i['updated_at'], ).init_id() obj.append(_set.mongo_dict()) await use_collection(TaskEnv.CLN_PROJECT).insert_many(obj) return res.json() async def create_project_price(self): projects = await use_collection(TaskEnv.CLN_PROJECT).find( {'monitor.detail.first_amount': {'$exists': 1}}).to_list(None) for project in projects: sum_status = 0 sum_adjust = 0 status = await use_collection(TaskEnv.CLN_FINANCIAL_STATUS).find( {'project_id': project['_id'], 'amount': {'$exists': 1}}).to_list(None) if status: for i in status: sum_status += i['amount'] adjust = await use_collection(TaskEnv.CLN_FINANCIAL_ADJUST).find( {'project_id': project['_id'], 'amount': {'$exists': 1}}).to_list(None) if adjust: for i in adjust: sum_adjust += i['amount'] price = { '_id': uuid.uuid4(), 'project_id': project['_id'], 'first_amount': project['monitor']['detail']['first_amount'], 'amount_status': sum_status, 'amount_adjust': sum_adjust } await use_collection(TaskEnv.CLN_PROJECT_PRICE_REPORT).insert_one(price)