main.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. # -*- coding: utf-8 -*-
  2. from openerp import http
  3. from openerp.http import request
  4. from werkzeug.wrappers import Response
  5. from werkzeug.datastructures import Headers
  6. from datetime import datetime
  7. from dateutil.relativedelta import relativedelta as rd
  8. from dateutil.parser import parse
  9. from gzip import GzipFile
  10. from StringIO import StringIO as IO
  11. import simplejson as json
  12. import gzip
  13. import logging
  14. LOGGER = logging.getLogger(__name__)
  15. DATE_FORMAT = '%Y-%m-%d'
  16. GZIP_COMPRESSION_LEVEL = 9
  17. class Purchases(http.Controller):
  18. '''
  19. Get server date to send
  20. '''
  21. def get_server_date(self):
  22. return datetime.now().strftime(DATE_FORMAT)
  23. '''
  24. Get current user information
  25. '''
  26. def get_user(self):
  27. user = request.env.user
  28. return {
  29. 'id': user.id,
  30. 'name': user.name,
  31. 'displayName': user.display_name,
  32. 'currency': {
  33. 'id': user.company_id.currency_id.id,
  34. 'name': user.company_id.currency_id.name,
  35. 'displayName': user.company_id.currency_id.display_name,
  36. 'symbol': user.company_id.currency_id.symbol
  37. },
  38. 'company': {
  39. 'id': user.company_id.id,
  40. 'name': user.company_id.name,
  41. 'displayName': user.company_id.display_name
  42. }
  43. }
  44. '''
  45. Get currencies
  46. '''
  47. def get_currencies(self):
  48. return [{
  49. 'id': currency.id,
  50. 'name': currency.name,
  51. 'displayName': currency.display_name,
  52. 'base': currency.base,
  53. 'accuracy': currency.accuracy,
  54. 'rateSilent': currency.rate_silent,
  55. 'rounding': currency.rounding,
  56. 'symbol': currency.symbol,
  57. 'position': currency.position,
  58. 'decimalSeparator': currency.decimal_separator,
  59. 'decimalPlaces': currency.decimal_places,
  60. 'thousandsSeparator': currency.thousands_separator
  61. } for currency in request.env['res.currency'].search([('active', '=', True)])]
  62. '''
  63. Get all active journals
  64. '''
  65. def get_journals(self):
  66. return [{
  67. 'id': journal.id,
  68. 'name': journal.name,
  69. 'displayName': journal.display_name,
  70. 'code': journal.code,
  71. 'cashControl': journal.cash_control,
  72. 'type': journal.type,
  73. 'currency': {
  74. 'id': journal.currency.id,
  75. 'name': journal.currency.name,
  76. 'displayName': journal.currency.display_name
  77. },
  78. 'defaultDebitAccount': {
  79. 'id': journal.default_debit_account_id.id,
  80. 'name': journal.default_debit_account_id.name,
  81. 'displayName': journal.default_debit_account_id.display_name,
  82. 'code': journal.default_debit_account_id.code,
  83. 'exchange_rate': journal.default_credit_account_id.exchange_rate,
  84. 'foreignBalance': journal.default_credit_account_id.foreign_balance,
  85. 'reconcile': journal.default_credit_account_id.reconcile,
  86. 'debit': journal.default_credit_account_id.debit,
  87. 'credit': journal.default_credit_account_id.credit,
  88. 'currencyMode': journal.default_credit_account_id.currency_mode,
  89. 'companyCurrency': {
  90. 'id': journal.default_credit_account_id.company_currency_id.id,
  91. 'name': journal.default_credit_account_id.company_currency_id.name,
  92. 'displayName': journal.default_credit_account_id.company_currency_id.display_name,
  93. },
  94. 'currency': {
  95. 'id': journal.default_credit_account_id.currency_id.id,
  96. 'name': journal.default_credit_account_id.currency_id.name,
  97. 'displayName': journal.default_credit_account_id.currency_id.display_name
  98. }
  99. }
  100. } for journal in request.env['account.journal'].search([('type', 'in', ['bank', 'cash']), ('default_debit_account_id.currency_id', '=', False), ('active', '=', True)], order='id')]
  101. '''
  102. Get all active suppliers
  103. '''
  104. def get_suppliers(self):
  105. return [{
  106. 'id': supplier.id,
  107. 'name': supplier.name,
  108. 'displayName': supplier.display_name,
  109. 'imageMedium': supplier.image_medium,
  110. 'phone': supplier.phone,
  111. 'mobile': supplier.mobile,
  112. 'email': supplier.email
  113. } for supplier in request.env['res.partner'].search([('supplier', '=', True), ('active', '=', True)])]
  114. '''
  115. Get all purchasable and active products
  116. '''
  117. def get_products(self):
  118. return [{
  119. 'id': product.id,
  120. 'name': product.name,
  121. 'displayName': product.display_name,
  122. 'ean13': product.ean13,
  123. 'imageMedium': product.image_medium,
  124. 'standardPrice': product.standard_price,
  125. 'variantCount': product.product_variant_count,
  126. 'quantity': 1,
  127. 'price': product.standard_price,
  128. 'variants': [{
  129. 'id': variant.id,
  130. 'name': variant.name,
  131. 'displayName': variant.display_name,
  132. 'ean13': variant.ean13,
  133. 'imageMedium': variant.image_medium,
  134. 'standardPrice': variant.standard_price,
  135. 'quantity': 1,
  136. 'price': variant.standard_price
  137. } for variant in product.product_variant_ids if variant.active]
  138. } for product in request.env['product.template'].search([('purchase_ok', '=', True), ('standard_price', '>=', 0), ('active', '=', True)])]
  139. '''
  140. Get all incoming and active picking types
  141. '''
  142. def get_picking_types(self):
  143. return [{
  144. 'id': picking_type.id,
  145. 'name': picking_type.name,
  146. 'displayName': picking_type.display_name
  147. } for picking_type in request.env['stock.picking.type'].search([('code', '=', 'incoming'), ('active', '=', True)])]
  148. '''
  149. Get all active payment terms
  150. '''
  151. def get_payment_terms(self):
  152. return [{
  153. 'id': payment_term.id,
  154. 'name': payment_term.name,
  155. 'displayName': payment_term.display_name,
  156. 'lines': [{
  157. 'id': line.id,
  158. 'days': line.days,
  159. 'days2': line.days2,
  160. 'value': line.value,
  161. 'valueAmount': line.value_amount
  162. } for line in payment_term.line_ids]
  163. } for payment_term in request.env['account.payment.term'].search([('active', '=', True)])]
  164. '''
  165. Make JSON response to send
  166. '''
  167. def make_response(self, data=None, status=200):
  168. return Response(json.dumps(data), status=status, content_type='application/json')
  169. '''
  170. Make GZIP to JSON response
  171. '''
  172. def make_gzip_response(self, data=None, status=200):
  173. gzip_buffer = IO()
  174. with GzipFile(mode='wb', compresslevel=GZIP_COMPRESSION_LEVEL, fileobj=gzip_buffer) as gzip_file:
  175. gzip_file.write(json.dumps(data))
  176. contents = gzip_buffer.getvalue()
  177. gzip_buffer.close()
  178. headers = Headers()
  179. headers.add('Content-Encoding', 'gzip')
  180. headers.add('Vary', 'Accept-Encoding')
  181. headers.add('Content-Length', len(contents))
  182. return Response(contents, status=status, headers=headers, content_type='application/json')
  183. '''
  184. '''
  185. def make_info_log(self, log):
  186. LOGGER.info('\033[1;34m[INFO] --> \033[m{}'.format(log))
  187. '''
  188. New purchase resource route
  189. '''
  190. @http.route('/eiru_purchases/init', auth='user', methods=['GET'], cors='*')
  191. def init_purchase(self, **kw):
  192. self.make_info_log('Sending JSON response')
  193. return self.make_gzip_response({
  194. 'date': self.get_server_date(),
  195. 'user': self.get_user(),
  196. 'currencies': self.get_currencies(),
  197. 'journals': self.get_journals(),
  198. 'suppliers': self.get_suppliers(),
  199. 'products': self.get_products(),
  200. 'pickingTypes': self.get_picking_types(),
  201. 'paymentTerms': self.get_payment_terms()
  202. })
  203. '''
  204. Create supplier and return data
  205. '''
  206. @http.route('/eiru_purchases/create_supplier', type='json', auth='user', methods=['POST'], cors='*')
  207. def create_supplier(self, **kw):
  208. self.make_info_log('Creating supplier')
  209. supplier = request.env['res.partner'].create({
  210. 'name': kw.get('name'),
  211. 'ruc': kw.get('ruc'),
  212. 'phone': kw.get('phone'),
  213. 'supplier': True,
  214. 'customer': False
  215. })
  216. return {
  217. 'id': supplier.id,
  218. 'name': supplier.name,
  219. 'displayName': supplier.display_name,
  220. 'imageMedium': supplier.image_medium,
  221. 'phone': supplier.phone,
  222. 'mobile': supplier.mobile,
  223. 'email': supplier.email
  224. }
  225. '''
  226. Create product and return data
  227. '''
  228. @http.route('/eiru_purchases/create_product', type='json', auth='user', methods=['POST'], cors='*')
  229. def create_product(self, **kw):
  230. self.make_info_log('Creating product')
  231. product = request.env['product.template'].create({
  232. 'name': kw.get('name'),
  233. 'standard_price': float(kw.get('price')),
  234. 'ean13': kw.get('ean13')
  235. })
  236. return {
  237. 'id': product.id,
  238. 'name': product.name,
  239. 'displayName': product.display_name,
  240. 'ean13': product.ean13,
  241. 'imageMedium': product.image_medium,
  242. 'listPrice': product.list_price,
  243. 'variantCount': product.product_variant_count,
  244. 'variants': [{
  245. 'id': variant.id,
  246. 'name': variant.name,
  247. 'displayName': variant.display_name,
  248. 'ean13': variant.ean13,
  249. 'imageMedium': variant.image_medium,
  250. 'standardPrice': variant.standard_price
  251. } for variant in product.product_variant_ids if variant.active]
  252. }
  253. '''
  254. Get currency id based on journal
  255. '''
  256. def get_currency_id(self, journal_id):
  257. journal = request.env['account.journal'].browse(journal_id)
  258. return journal.default_debit_account_id.currency_id.id or journal.default_debit_account_id.company_currency_id.id
  259. '''
  260. Check currency in pricelist and return it
  261. '''
  262. def get_pricelist_id(self, currency_id):
  263. pricelist = request.env['product.pricelist'].search([('active', '=', True), ('type', '=', 'sale')])
  264. if not True in pricelist.mapped(lambda p: p.currency_id.id == currency_id):
  265. pricelist = pricelist[0].copy()
  266. pricelist.write({
  267. 'currency_id': currency_id
  268. })
  269. else:
  270. pricelist = pricelist.filtered(lambda p: p.currency_id.id == currency_id)
  271. return pricelist.id
  272. '''
  273. Get default location
  274. '''
  275. def get_stock_location_id(self):
  276. stock_location = request.env['stock.location'].search([('usage', '=', 'internal')])
  277. return stock_location.id
  278. '''
  279. Create purchase order from cart and return id
  280. '''
  281. def create_purchase_order(self, supplier_id, cart_items, date_order, currency_id, pricelist_id, payment_term_id=None):
  282. return request.env['purchase.order'].create({
  283. 'name': '/',
  284. 'partner_id': supplier_id,
  285. 'order_line': [[0, False, {
  286. 'name': line.get('name'),
  287. 'date_planned': date_order,
  288. 'product_id': int(line.get('id')),
  289. 'product_qty': float(line.get('quantity')),
  290. 'price_unit': float(line.get('price'))
  291. }] for line in cart_items],
  292. 'date_order': date_order,
  293. 'currency_id': currency_id,
  294. 'pricelist_id': pricelist_id,
  295. 'payment_term_id': payment_term_id,
  296. 'location_id': self.get_stock_location_id(),
  297. 'invoice_method': 'manual',
  298. 'state': 'draft'
  299. })
  300. '''
  301. Confirm purchase order
  302. '''
  303. def confirm_purchase_order(self, purchase_order_id):
  304. purchase_order = request.env['purchase.order'].browse(purchase_order_id)
  305. purchase_order.write({
  306. 'state': 'confirmed'
  307. })
  308. purchase_order.action_purchase_confirm()
  309. for picking in purchase_order.picking_ids:
  310. picking.force_assign()
  311. picking.action_done()
  312. '''
  313. Purchase order
  314. '''
  315. def create_invoice(self, purchase_order_id):
  316. purchase_order_obj = request.env['purchase.order']
  317. purchase_order_line_obj = request.env['purchase.order.line']
  318. purchase_order_line_invoice_obj = request.env['purchase.order.line_invoice']
  319. account_invoice_line_obj = request.env['account.invoice.line']
  320. purchase_order = purchase_order_obj.browse(purchase_order_id)
  321. invoice_lines = {}
  322. for line in purchase_order.order_line:
  323. if (not line.invoiced) and (line.state not in ('draft', 'cancel')):
  324. if not line.partner_id.id in invoice_lines:
  325. invoice_lines[line.partner_id.id] = []
  326. account_id = purchase_order_obj._choose_account_from_po_line(line)
  327. account_invoice_line_values = purchase_order_obj._prepare_inv_line(account_id, line)
  328. account_invoice_line_values.update({
  329. 'origin': line.order_id.name
  330. })
  331. account_invoice_line_id = account_invoice_line_obj.create(account_invoice_line_values)
  332. purchase_order_line_obj.with_context({
  333. 'invoiced': True,
  334. 'invoice_lines': [(4, account_invoice_line_id.id)]
  335. }).write([line.id])
  336. invoice_lines[line.partner_id.id].append((line, account_invoice_line_id.id))
  337. invoice_ids = []
  338. for value in invoice_lines.values():
  339. invoice_line = map(lambda x : x[1], value)
  340. orders = list(set(map(lambda x : x[0].order_id, value)))
  341. new_id = purchase_order_line_invoice_obj._make_invoice_by_partner(orders[0].partner_id, orders, invoice_line)
  342. invoice_ids.append(new_id)
  343. return invoice_ids
  344. '''
  345. Purchase processing resource route
  346. '''
  347. @http.route('/eiru_purchases/process', type='json', auth='user', methods=['POST'], cors='*')
  348. def process_purchase(self, **kw):
  349. self.make_info_log('Processing purchase...')
  350. # # Get date
  351. date_now = datetime.now().strftime(DATE_FORMAT)
  352. self.make_info_log('Getting date')
  353. # Get currency
  354. currency_id = self.get_currency_id(kw.get('journalId'))
  355. self.make_info_log('Getting currency')
  356. # Get pricelist
  357. pricelist_id = self.get_pricelist_id(currency_id)
  358. self.make_info_log('Product pricelist checked')
  359. # Create purchase order
  360. purchase_order = self.create_purchase_order(kw.get('supplierId'), kw.get('items'), date_now, currency_id, pricelist_id, kw.get('paymentTermId'))
  361. self.make_info_log('Purchase order created')
  362. # Confirm purchase
  363. self.confirm_purchase_order(purchase_order.id)
  364. self.make_info_log('Purchase order confirmed')
  365. # Create invoice
  366. invoice_ids = self.create_invoice(purchase_order.id)
  367. self.make_info_log('Invoice created')
  368. print(invoice_ids)
  369. return {
  370. 'status': 'ok'
  371. }