dbread.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. '''
  2. Created on Jun 21, 2018 @author: levente.marton
  3. '''
  4. import os
  5. import shutil
  6. import re
  7. import datetime
  8. from dataclasses import dataclass
  9. from pypxlib import Table
  10. @dataclass
  11. class Company:
  12. name: str
  13. vat_code: str
  14. reg_number: str
  15. address: str
  16. location: str
  17. county: str
  18. shortname: str
  19. obs: str
  20. adm: str
  21. admp: str
  22. admcnp: str
  23. mail: str = None
  24. price: int = None
  25. @dataclass
  26. class Account:
  27. clasa: str
  28. simbol: str
  29. denumire: str
  30. soldid: str = None
  31. soldic: str = None
  32. precedentd: str = None
  33. precedentc: str = None
  34. curentd: str = None
  35. curentc: str = None
  36. def soldf(self, type_):
  37. if type_ == 'd':
  38. return round((self.soldid + self.precedentd + self.curentd) -
  39. (self.soldic + self.precedentc + self.curentc))
  40. elif type_ == 'c':
  41. return round((self.soldic + self.precedentc + self.curentc) -
  42. (self.soldid + self.precedentd + self.curentd))
  43. class WinMentor(object):
  44. '''
  45. Class to read winmentor database
  46. '''
  47. def __init__(self, winment_path=os.getenv('WINMENT', 'c:/winment/data/').replace('\\', '/')):
  48. '''
  49. Constructor
  50. '''
  51. self.winment_path = winment_path
  52. @property
  53. def get_winment_path(self):
  54. return self.winment_path
  55. @get_winment_path.setter
  56. def set_winment_path(self, value):
  57. # self.value = value
  58. self.winment_path = value
  59. return self.winment_path
  60. def update_copy(self, db_file) -> str:
  61. '''returns the updated version of a .db file
  62. :param db_file is a .db from winmentor'''
  63. # self._to_file = db_file
  64. _, file_name = os.path.split(db_file)
  65. dir_list = db_file.split('/')
  66. # !!NOTE: if path is ?/winment/data/ then this must be 3 & 5
  67. # if is ?/winment/winment/data/ then 4 & 6
  68. dir_to_file = dir_list[4]
  69. if len(dir_list) != 6:
  70. os.makedirs(os.path.join('cash', dir_to_file), exist_ok=True)
  71. cashed_copy_mtime = -1
  72. if os.path.isfile(os.path.join('./cash/', dir_to_file, file_name)):
  73. cashed_copy_mtime = os.stat(os.path.join('./cash/', dir_to_file, file_name)).st_mtime
  74. if os.stat(db_file).st_mtime != cashed_copy_mtime:
  75. shutil.copy2(db_file, os.path.join('./cash', dir_to_file))
  76. return(os.path.join('./cash/', dir_to_file, file_name))
  77. else:
  78. os.makedirs('cash', exist_ok=True)
  79. cashed_copy_mtime = -1
  80. if os.path.isfile('./cash/' + file_name):
  81. cashed_copy_mtime = os.stat('./cash/' + file_name).st_mtime
  82. if os.stat(db_file).st_mtime != cashed_copy_mtime:
  83. shutil.copy2(db_file, './cash')
  84. return('./cash/' + file_name)
  85. def make_list(self, db_file, headers) -> list:
  86. '''returns a list of lists with elements from a given db file
  87. :param db_file is .db file from winmentor
  88. :param headers are the fields of the specified db file'''
  89. file_name = self.update_copy(db_file)
  90. with Table(file_name) as table:
  91. m_list = []
  92. for row in table:
  93. item = []
  94. for header in headers:
  95. element = row[header]
  96. if type(element) == datetime.date:
  97. if element < datetime.date(1999, 1, 1):
  98. element = ''
  99. item.append(element)
  100. m_list.append(item)
  101. return m_list
  102. def make_sal_list(self, file_1, file_2) -> list:
  103. '''returns list with all employees in current month
  104. :param file_1 is npers.db from shortname
  105. :param file_2 is likisal.db shortname/current_month'''
  106. file_name1 = self.update_copy(self.winment_path + file_1)
  107. file_name2 = self.update_copy(self.winment_path + file_2)
  108. with Table(file_name1) as perss, Table(file_name2) as sals:
  109. empl_all = []
  110. # for field in perss.fields:
  111. for sal in sals:
  112. for pers in perss:
  113. # print(pers)
  114. if pers.Cod == sal.Cod:
  115. empl = []
  116. empl.append(pers.Cod)
  117. empl.append(f'{pers.Nume} {pers.Prenume}')
  118. empl.append(pers.DataAngF.strftime('%d-%m-%Y'))
  119. empl.append(sal.VenitBrut)
  120. empl.append(sal.SalRealizat)
  121. empl.append(sal.CO)
  122. empl.append(round(sal.SalOra, 2))
  123. empl.append(sal.ContribAngajat)
  124. empl.append(round(sal.ContribAngajator, 2))
  125. empl.append(sal.VenitNet)
  126. empl.append(sal.Impozit)
  127. empl.append(sal.SalarNet)
  128. empl.append(sal.OreLucrate)
  129. empl.append(sal.ZileLuk)
  130. empl.append(sal.ZileCO)
  131. empl_all.append(empl)
  132. # dict_ = {}
  133. # dict_['Cod'] = pers.Cod
  134. # dict_['Nume'] = f'{pers.Nume} {pers.Prenume}'
  135. # dict_['DataAngF'] = pers.DataAngF.strftime('%d-%m-%Y')
  136. # dict_['VenitBrut'] = sal.VenitBrut
  137. # dict_['SalRealizat'] = sal.SalRealizat
  138. # dict_['CO'] = sal.CO
  139. # dict_['SalOra'] = round(sal.SalOra, 2)
  140. # dict_['ContribAngajat'] = sal.ContribAngajat
  141. # dict_['ContribAngajator'] = round(sal.ContribAngajator, 2)
  142. # dict_['VenitNet'] = sal.VenitNet
  143. # dict_['Impozit'] = sal.Impozit
  144. # dict_['SalarNet'] = sal.SalarNet
  145. # dict_['OreLucrate'] = sal.OreLucrate
  146. # dict_['ZileLuk'] = sal.ZileLuk
  147. # dict_['ZileCO'] = sal.ZileCO
  148. # empl.append(dict_)
  149. return empl_all
  150. def gen_firms(self, db_file, headers) -> list:
  151. '''generates company list from firme.db file
  152. :param db_file is firme.db from winment/data folder'''
  153. file_db = self.update_copy(self.winment_path + db_file)
  154. with Table(file_db) as table:
  155. for row in table:
  156. yield [row[header] for header in headers]
  157. def firmlist(self, headers, db_file='/firme.db', ban=None) -> list:
  158. '''returns company list from firme.db file
  159. :param db_file is firme.db from winment/data folder
  160. :param list headers is the fields from firme.db file
  161. :param list|str ban companies excluded from list'''
  162. comp_list = []
  163. for a_company in self.gen_firms(db_file, headers):
  164. company = Company(
  165. name=a_company[0],
  166. vat_code=a_company[1],
  167. reg_number=a_company[2],
  168. address=a_company[3],
  169. location=a_company[4],
  170. county=a_company[5],
  171. shortname=a_company[6],
  172. adm=a_company[7],
  173. admp=a_company[8],
  174. admcnp=a_company[9],
  175. obs=a_company[10])
  176. comp_list.append(company)
  177. if ban:
  178. if type(ban) is list:
  179. for r in comp_list:
  180. for company_shortname in ban:
  181. if company_shortname == r.shortname:
  182. comp_list.remove(r)
  183. else:
  184. for r in comp_list:
  185. if r == ban:
  186. comp_list.remove(r)
  187. return comp_list
  188. def filtered_firmlist(self, headers, db_file='/firme.db', ban=None) -> list:
  189. '''generates company list from firme.db file
  190. :param db_file is firme.db from winment/data folder
  191. :param list headers is the fields from firme.db file
  192. :param list|str ban companies excluded from list'''
  193. if ban:
  194. if type(ban) is list:
  195. for a_company in self.gen_firms(db_file, headers):
  196. company = Company(
  197. name=a_company[0],
  198. vat_code=a_company[1],
  199. reg_number=a_company[2],
  200. address=a_company[3],
  201. location=a_company[4],
  202. county=a_company[5],
  203. shortname=a_company[6],
  204. adm=a_company[7],
  205. admp=a_company[8],
  206. admcnp=a_company[9],
  207. obs=a_company[10])
  208. if a_company[6] not in ban:
  209. yield [company.name, company.vat_code, company.reg_number,
  210. company.address, company.location, company.county,
  211. company.shortname, company.adm, company.admp,
  212. company.admcnp, company.obs]
  213. else:
  214. for a_company in self.gen_firms(db_file, headers):
  215. company = Company(
  216. name=a_company[0],
  217. vat_code=a_company[1],
  218. reg_number=a_company[2],
  219. address=a_company[3],
  220. location=a_company[4],
  221. county=a_company[5],
  222. shortname=a_company[6],
  223. adm=a_company[7],
  224. admp=a_company[8],
  225. admcnp=a_company[9],
  226. obs=a_company[10])
  227. yield [company.name, company.vat_code, company.reg_number,
  228. company.address, company.location, company.county,
  229. company.shortname, company.adm, company.admp,
  230. company.admcnp, company.obs]
  231. def get_last_month(self, short_name) -> str:
  232. '''returns last month of a company in format YYYY_MM
  233. :param str short_name is the company shortname'''
  234. short_name = self.winment_path + short_name
  235. month_folders = [f for f in os.listdir(short_name) if re.match(r'[0-9_]+$', f)]
  236. month_folders.reverse()
  237. return month_folders[0]
  238. def corp_list(self, name=None):
  239. '''returns company list from actual shortnames from winmwnt/data folder
  240. '''
  241. dir_list = [f.name for f in os.scandir(self.winment_path) if f.is_dir() and '@' not in f.name]
  242. if name:
  243. if type(name) is list:
  244. for r in name:
  245. dir_list.remove(r)
  246. else:
  247. dir_list.remove(name)
  248. return dir_list
  249. def verif_corp(self, file_='/firme.db', ban=None):
  250. headers = ['Denumire', 'CF', 'J', 'Adresa', 'Oras', 'Judet', 'Prescurtat', 'Obs']
  251. corplist = self.make_list(self.winment_path + file_, headers) # dbRead.make_list(m_path + '/FIRME.DB', headers)
  252. if ban:
  253. if type(ban) is list:
  254. for r in corplist:
  255. for i in ban:
  256. if i == r[6]:
  257. corplist.remove(r)
  258. else:
  259. for r in corplist:
  260. if r == ban:
  261. corplist.remove(r)
  262. return corplist
  263. def verif_cont(self, file_) -> list:
  264. '''returns an account with its values from the balance
  265. :param file_ is shortname/ncont.db'''
  266. accounts = []
  267. headers = ['Clasa', 'Simbol', 'Denumire', 'SoldID', 'SoldIC', 'PrecedentD', 'PrecedentC', 'CurentD', 'CurentC']
  268. accountlist = self.make_list(self.winment_path + file_, headers) # + lunaCurenta
  269. for elem in accountlist:
  270. account = Account(clasa=elem[0],
  271. simbol=elem[1],
  272. denumire=elem[2],
  273. soldid=elem[3],
  274. soldic=elem[4],
  275. precedentd=elem[5],
  276. precedentc=elem[6],
  277. curentd=elem[7],
  278. curentc=elem[8])
  279. accounts.append(account)
  280. return accountlist
  281. def an_inc(self, account_list, boolind, ind2, ind3):
  282. '''returns the annual turnover in given year
  283. :param int boolind:account class number
  284. :param int ind2, ind3:debit or credit position in balance
  285. (6-rulaj curent debit, 8-rulaj cumulat debit, index starting from 0)'''
  286. tt = 0
  287. for account in account_list:
  288. # n = len(account[boolind]) == 3 and account[boolind] != '...' and int(account[boolind]) > 700 and int(account[boolind]) < 760
  289. n = account[boolind] == 7
  290. can = account[1][:2] != '76'
  291. # print(account[1][:2])
  292. if n and can:
  293. tt += int(account[ind2]) + int(account[ind3])
  294. return tt
  295. def divid(self, account_list, account='457') -> int:
  296. '''returns dividends/year
  297. :param account_list is account from ncont.db'''
  298. div_ = 0
  299. for acc in account_list:
  300. if acc[1][:3] == account:
  301. div_ += acc[8] + acc[6]
  302. return round(div_)
  303. def divid_current(self, account_list, account='457') -> int:
  304. '''returns dividends from current month
  305. :param account_list is account from ncont.db'''
  306. div_ = 0
  307. for acc in account_list:
  308. if acc[1][:3] == account:
  309. div_ += acc[8]
  310. return round(div_)
  311. def divid_intermed(self, account_list, account='463') -> int:
  312. '''returns dividends from current result/year
  313. :param account_list is account from ncont.db'''
  314. div_ = 0
  315. for acc in account_list:
  316. if acc[1][:3] == account:
  317. div_ += acc[7] + acc[5]
  318. return round(div_)
  319. def divid_inter_current(self, account_list, account='463') -> int:
  320. '''returns dividends from current results in the current month
  321. :param account_list is account from ncont.db'''
  322. div_ = 0
  323. for acc in account_list:
  324. if acc[1][:3] == account:
  325. div_ += acc[7]
  326. return round(div_)
  327. def spons(self, account_list, account='658.02') -> int:
  328. '''returns sponsored money/year
  329. :param account_list is account from ncont.db'''
  330. spons_ = 0
  331. for acc in account_list:
  332. if acc[1] == account:
  333. spons_ += acc[8] + acc[6]
  334. return round(spons_)
  335. def result(self, account_list, boolind, ind2, ind3) -> int: # account='121'
  336. '''returns the final result in given year
  337. :param int boolind:account class number
  338. :param int ind2, ind3:debit or credit position in balance
  339. (6-rulaj curent debit, 8-rulaj cumulat debit, index starting from 0)'''
  340. res_minus = res_plus = 0
  341. for r_minus in account_list:
  342. p = r_minus[boolind] == 6
  343. if p:
  344. res_minus += int(r_minus[ind2]) + int(r_minus[ind3])
  345. for r_plus in account_list:
  346. i = r_plus[boolind] == 7
  347. if i:
  348. res_plus += int(r_plus[ind2]) + int(r_plus[ind3])
  349. return res_plus - res_minus
  350. def ins_payable(self, account_list, account='431') -> int:
  351. '''returns insurences payable in current month
  352. :param account_list is account from ncont.db'''
  353. ins = 0
  354. for acc in account_list:
  355. p = acc[1][:3] == account
  356. if p:
  357. ins += acc[8]
  358. return round(ins)
  359. def CAS_payable(self, account_list, accounts=('431.02', '431.05')) -> int:
  360. '''returns CAS payable in current month
  361. :param account_list is account from ncont.db'''
  362. CAS = 0
  363. acc_1, acc_2 = accounts
  364. for acc in account_list:
  365. p = acc[1] == acc_1
  366. d = acc[1] == acc_2
  367. if p: CAS += acc[8]
  368. if d: CAS += acc[8]
  369. return round(CAS)
  370. def CASS_payable(self, account_list, accounts=('431.04', '431.06')) -> int:
  371. '''returns CASS payable in current month
  372. :param account_list is account from ncont.db'''
  373. CASS = 0
  374. acc_1, acc_2 = accounts
  375. for acc in account_list:
  376. p = acc[1] == acc_1
  377. d = acc[1] == acc_2
  378. if p: CASS += acc[8]
  379. if d: CASS += acc[8]
  380. return round(CASS)
  381. def sal_tax_payable(self, account_list, account='431.44') -> int:
  382. '''returns salary tax payable in current month
  383. :param account_list is account from ncont.db'''
  384. tax = 0
  385. for acc in account_list:
  386. p = acc[1] == account
  387. if p:
  388. tax += acc[8]
  389. return round(tax)
  390. def cam_payable(self, account_list, account='436') -> int:
  391. '''returns CAM payable in current month
  392. :param account_list is account from ncont.db'''
  393. cam = 0
  394. for acc in account_list:
  395. p = acc[1][:3] == account
  396. if p:
  397. cam += acc[8]
  398. return round(cam)
  399. def vat_payable(self, account_list, accounts=('442.03', '442.04')) -> int:
  400. '''returns VAT payable in current month
  401. :param account_list is account from ncont.db'''
  402. tt = 0
  403. acc_1, acc_2 = accounts
  404. for acc in account_list:
  405. p = acc[1] == acc_1
  406. d = acc[1] == acc_2
  407. if p:
  408. tt += acc[8]
  409. elif d:
  410. tt -= acc[7] + acc[8]
  411. return round(tt)
  412. def vat_final(self, acc_list, accounts=('442.03', '442.04')) -> int:
  413. '''returns VAT final payable in current month
  414. :param account_list is account from ncont.db'''
  415. tt = 0
  416. acc_1, acc_2 = accounts
  417. for acc in acc_list:
  418. account = Account(clasa=acc[0],
  419. simbol=acc[1],
  420. denumire=acc[2],
  421. soldid=acc[3],
  422. soldic=acc[4],
  423. precedentd=acc[5],
  424. precedentc=acc[6],
  425. curentd=acc[7],
  426. curentc=acc[8])
  427. payable = account.simbol == acc_1
  428. deductible = account.simbol == acc_2
  429. if payable:
  430. tt += account.soldf('c')
  431. elif deductible:
  432. tt -= account.soldf('d')
  433. return round(tt)
  434. def tax_payable(self, account_list, account='441') -> int:
  435. '''returns income TAX payable in current month
  436. :param account_list is account from ncont.db'''
  437. tax = 0
  438. for acc in account_list:
  439. p = acc[1][:3] == account
  440. if p:
  441. tax += acc[8]
  442. return round(tax)
  443. def div_tax_payable(self, acc_list, accounts='446.07') -> int:
  444. '''returns dividend TAX payable in current month
  445. :param account_list is account from ncont.db'''
  446. tt = 0
  447. # acc_1, acc_2 = accounts
  448. for acc in acc_list:
  449. account = Account(clasa=acc[0],
  450. simbol=acc[1],
  451. denumire=acc[2],
  452. soldid=acc[3],
  453. soldic=acc[4],
  454. precedentd=acc[5],
  455. precedentc=acc[6],
  456. curentd=acc[7],
  457. curentc=acc[8])
  458. payable = account.simbol == accounts
  459. # deductible = account.simbol == acc_2
  460. if payable:
  461. tt += account.curentc
  462. # elif deductible:
  463. # tt -= account.soldf('d')
  464. return round(tt)
  465. def advance_final(self, acc_list, accounts='542') -> int:
  466. '''returns final dvances/year
  467. :param account_list is account from ncont.db'''
  468. tt = 0
  469. # acc_1, acc_2 = accounts
  470. for acc in acc_list:
  471. account = Account(clasa=acc[0],
  472. simbol=acc[1],
  473. denumire=acc[2],
  474. soldid=acc[3],
  475. soldic=acc[4],
  476. precedentd=acc[5],
  477. precedentc=acc[6],
  478. curentd=acc[7],
  479. curentc=acc[8])
  480. payable = account.simbol[:3] == accounts
  481. # deductible = account.simbol == acc_2
  482. if payable:
  483. tt += account.soldf('d')
  484. # elif deductible:
  485. # tt -= account.soldf('d')
  486. return round(tt)
  487. def deb_div(self, acc_list, accounts='461') -> int:
  488. '''returns advances transfered to deb. diversi/year
  489. :param account_list is account from ncont.db'''
  490. tt = 0
  491. # acc_1, acc_2 = accounts
  492. for acc in acc_list:
  493. account = Account(clasa=acc[0],
  494. simbol=acc[1],
  495. denumire=acc[2],
  496. soldid=acc[3],
  497. soldic=acc[4],
  498. precedentd=acc[5],
  499. precedentc=acc[6],
  500. curentd=acc[7],
  501. curentc=acc[8])
  502. payable = account.simbol[:3] == accounts
  503. # deductible = account.simbol == acc_2
  504. if payable:
  505. tt += account.soldf('d')
  506. # elif deductible:
  507. # tt -= account.soldf('d')
  508. return round(tt)
  509. def credit_final(self, acc_list, accounts='455') -> int:
  510. '''returns credited ammount/year
  511. :param account_list is account from ncont.db'''
  512. tt = 0
  513. # acc_1, acc_2 = accounts
  514. for acc in acc_list:
  515. account = Account(clasa=acc[0],
  516. simbol=acc[1],
  517. denumire=acc[2],
  518. soldid=acc[3],
  519. soldic=acc[4],
  520. precedentd=acc[5],
  521. precedentc=acc[6],
  522. curentd=acc[7],
  523. curentc=acc[8])
  524. payable = account.simbol[:3] == accounts
  525. # deductible = account.simbol == acc_2
  526. if payable:
  527. tt += account.soldf('d')
  528. # elif deductible:
  529. # tt -= account.soldf('d')
  530. return round(tt)