main.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. # -*- coding: utf-8 -*-
  2. from openerp import api, http
  3. from openerp.http import request
  4. from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, float_round
  5. from werkzeug.wrappers import Response
  6. from werkzeug.datastructures import Headers
  7. from datetime import datetime
  8. from dateutil.relativedelta import relativedelta as rd
  9. from dateutil.parser import parse
  10. from pytz import timezone
  11. from gzip import GzipFile
  12. import simplejson as json
  13. import gzip
  14. import logging
  15. try:
  16. from cStringIO import StringIO as IO
  17. except ImportError:
  18. from StringIO import StringIO as IO
  19. LOGGER = logging.getLogger(__name__)
  20. GZIP_COMPRESSION_LEVEL = 9
  21. '''
  22. ___ ___ __ __ __ ___ __ __ ___ __ ___ __ __ __ __ __
  23. |__| | | |__) / ` / \ |\ | | |__) / \ | | |__ |__) |__ / \ |__) |__) / \ /__`
  24. | | | | | \__, \__/ | \| | | \ \__/ |___ |___ |___ | \ | \__/ | \ | \__/ .__/
  25. # Resource paths
  26. - /init: return json response gzip compressed contains values for sale operation
  27. - /create_product: create product on the fly POS and return it
  28. - /create_customer: create customer on the fly and return it
  29. - /process_sale: processing sale and return true if completed
  30. '''
  31. class PosSales(http.Controller):
  32. '''
  33. Make JSON response
  34. '''
  35. def make_json_response(self, data=None, status=200):
  36. return Response(json.dumps(data), status=status, content_type='application/json')
  37. '''
  38. Make GZIP to JSON response
  39. '''
  40. def make_gzip_response(self, data=None, status=200):
  41. gzip_buffer = IO()
  42. with GzipFile(mode='wb', compresslevel=GZIP_COMPRESSION_LEVEL, fileobj=gzip_buffer) as gzip_file:
  43. gzip_file.write(json.dumps(data))
  44. contents = gzip_buffer.getvalue()
  45. gzip_buffer.close()
  46. headers = Headers()
  47. headers.add('Content-Encoding', 'gzip')
  48. headers.add('Vary', 'Accept-Encoding')
  49. headers.add('Content-Length', len(contents))
  50. return Response(contents, status=status, headers=headers, content_type='application/json')
  51. '''
  52. '''
  53. def make_info_log(self, log):
  54. LOGGER.info(log)
  55. '''
  56. Get POS data
  57. '''
  58. def get_pos_settings(self):
  59. settings = request.env['base.config.settings'].search([], limit=1, order='id desc')
  60. return {
  61. 'imageType': settings.image_type,
  62. 'allowCurrencyExchange': settings.allow_currency_exchange,
  63. 'viewCurrencyExchanges': settings.view_currency_exchanges,
  64. 'currencies': [
  65. {
  66. 'id': currency.id,
  67. 'name': currency.display_name,
  68. 'symbol': currency.symbol,
  69. 'position': currency.position,
  70. 'rateSilent': currency.rate_silent,
  71. 'decimalSeparator': currency.decimal_separator,
  72. 'decimalPlaces': currency.decimal_places,
  73. 'thousandsSeparator': currency.thousands_separator
  74. } for currency in settings.currency_ids
  75. ]
  76. }
  77. '''
  78. Get timezone
  79. '''
  80. def get_timezone(self):
  81. return timezone(request.context['tz'])
  82. '''
  83. Get server date
  84. '''
  85. def get_server_datetime(self):
  86. return datetime.now(self.get_timezone()).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
  87. '''
  88. Check if module is installed
  89. '''
  90. def is_module_installed(self, module_name):
  91. domain = [('name', '=', module_name), ('state', '=', 'installed')]
  92. module = request.env['ir.module.module'].search(domain)
  93. return len(module) != 0
  94. '''
  95. Get current user information
  96. '''
  97. def get_user(self):
  98. user = request.env.user
  99. return {
  100. 'id': user.id,
  101. 'name': user.display_name,
  102. 'company': {
  103. 'id': user.company_id.id,
  104. 'name': user.company_id.display_name,
  105. 'phone': user.company_id.phone or None,
  106. 'city': user.company_id.city or None,
  107. 'currencyId': user.company_id.currency_id.id or None
  108. },
  109. 'isManager': 'Gerente' in user.groups_id.filtered(lambda g: g.category_id.name == 'Eiru POS').mapped(lambda g: g.name)
  110. }
  111. '''
  112. Get currencies from configured journals
  113. '''
  114. def get_currencies_from_journals(self):
  115. domain = [('type', 'in', ['bank', 'cash']), ('active', '=', True)]
  116. currencies = []
  117. for journal in request.env['account.journal'].search(domain):
  118. currency = journal.currency or journal.company_id.currency_id
  119. currencies.append({
  120. 'id': currency.id,
  121. 'name': currency.display_name,
  122. 'base': currency.base,
  123. 'symbol': currency.symbol,
  124. 'position': currency.position,
  125. 'rateSilent': currency.rate_silent,
  126. 'decimalSeparator': currency.decimal_separator,
  127. 'decimalPlaces': currency.decimal_places,
  128. 'thousandsSeparator': currency.thousands_separator
  129. })
  130. return {c['id']:c for c in currencies}.values()
  131. '''
  132. Get all active journals
  133. '''
  134. def get_journals(self):
  135. domain = [('type', 'in', ['bank', 'cash']), ('active', '=', True)]
  136. has_subtype = self.is_module_installed('eiru_bank_payments_references')
  137. if not self.get_pos_settings().get('allowCurrencyExchange'):
  138. currency_id = self.get_user().get('company').get('currencyId')
  139. domain.append('|')
  140. domain.append(('currency', '=', currency_id))
  141. domain.append(('company_id.currency_id', '=', currency_id))
  142. return [{
  143. 'id': journal.id,
  144. 'name': journal.display_name,
  145. 'code': journal.code,
  146. 'type': journal.type,
  147. 'subtype': (has_subtype and journal.subtype) or None,
  148. 'currencyId': journal.currency.id or journal.company_id.currency_id.id
  149. } for journal in request.env['account.journal'].search(domain, order='id')]
  150. '''
  151. Get banks
  152. '''
  153. def get_banks(self):
  154. banks = []
  155. if self.is_module_installed('eiru_bank_payments_references'):
  156. banks = [
  157. {
  158. 'id': bank.id,
  159. 'name': bank.display_name
  160. } for bank in request.env['res.bank'].search([('active', '=', True)])
  161. ]
  162. return banks
  163. '''
  164. Get bank payment types
  165. '''
  166. def get_bank_payment_types(self):
  167. bank_types = []
  168. if self.is_module_installed('eiru_bank_payments_references'):
  169. domain = [('is_receipt', '=', True)]
  170. bank_types = [
  171. {
  172. 'id': type.id,
  173. 'name': type.display_name,
  174. 'isReceipt': type.is_receipt,
  175. 'isPayment': type.is_payment,
  176. 'fieldsAllowed': map(lambda x: x.strip(), (type.fields_allowed or []).split(',')),
  177. 'subtype': type.subtype,
  178. 'defaultState': type.default_state
  179. } for type in request.env['res.bank.payments.type'].search(domain)
  180. ]
  181. return bank_types
  182. '''
  183. Get cheque
  184. '''
  185. def get_cheque_types(self):
  186. cheque_types = []
  187. if self.is_module_installed('eiru_bank_payments_references'):
  188. cheque_types = [
  189. {
  190. 'id': type.id,
  191. 'name': type.display_name,
  192. 'isBank': type.is_bank,
  193. 'isCash': type.is_cash
  194. } for type in request.env['res.bank.check.type'].search([])
  195. ]
  196. return cheque_types
  197. '''
  198. Get all active customers
  199. '''
  200. def get_customers(self, image_type='small'):
  201. domain = [('customer', '=', True), ('active', '=', True)]
  202. return [
  203. {
  204. 'id': customer.id,
  205. 'name': customer.display_name,
  206. 'image': customer.image_small if image_type == 'small' else customer.image_medium,
  207. 'ruc': customer.ruc or None,
  208. 'phone': customer.phone or None,
  209. 'mobile': customer.mobile or None,
  210. 'email': customer.email or None
  211. } for customer in request.env['res.partner'].search(domain)
  212. ]
  213. '''
  214. Get all saleable and active products
  215. '''
  216. def get_products(self, image_type='small'):
  217. domain = [('sale_ok', '=', True), ('list_price', '>', 0), ('active', '=', True)]
  218. return [
  219. {
  220. 'id': product.id,
  221. 'name': product.display_name,
  222. 'ean13': product.ean13,
  223. 'defaultCode': product.default_code,
  224. 'image': product.image_small if image_type == 'small' else product.image_medium,
  225. 'listPrice': product.list_price,
  226. 'variantCount': product.product_variant_count,
  227. 'quantity': 1,
  228. 'price': product.list_price,
  229. 'minimumPrice': product.minimum_price,
  230. 'maximumPrice': product.maximum_price,
  231. 'discount': 0,
  232. 'variants': [{
  233. 'id': variant.id,
  234. 'name': variant.display_name,
  235. 'ean13': variant.ean13,
  236. 'defaultCode': product.default_code,
  237. 'image': variant.image_small if image_type == 'small' else variant.image_medium,
  238. 'listPrice': variant.list_price,
  239. 'quantity': 1,
  240. 'price': variant.list_price,
  241. 'minimumPrice': product.minimum_price,
  242. 'maximumPrice': product.maximum_price,
  243. 'discount': 0,
  244. } for variant in product.product_variant_ids if variant.active]
  245. } for product in request.env['product.template'].search(domain)
  246. ]
  247. '''
  248. Get all active payment terms
  249. '''
  250. def get_payment_terms(self):
  251. domain = [('active', '=', True)]
  252. return [
  253. {
  254. 'id': payment_term.id,
  255. 'name': payment_term.display_name,
  256. 'lines': [{
  257. 'id': line.id,
  258. 'days': line.days,
  259. 'days2': line.days2,
  260. 'value': line.value,
  261. 'valueAmount': line.value_amount
  262. } for line in payment_term.line_ids]
  263. } for payment_term in request.env['account.payment.term'].search(domain)
  264. ]
  265. '''
  266. Get currency from journal
  267. '''
  268. def get_currency(self, journal_id):
  269. journal = request.env['account.journal'].browse(journal_id)
  270. return journal.default_credit_account_id.currency_id.id or journal.default_credit_account_id.company_currency_id.id
  271. '''
  272. Check currency in pricelist and get it
  273. '''
  274. def get_pricelist(self, currency_id):
  275. pricelist = request.env['product.pricelist'].search([('active', '=', True), ('type', '=', 'sale')])
  276. if not True in pricelist.mapped(lambda p: p.currency_id.id == currency_id):
  277. pricelist = pricelist[0].copy()
  278. pricelist.write({
  279. 'currency_id': currency_id
  280. })
  281. else:
  282. pricelist = pricelist.filtered(lambda p: p.currency_id.id == currency_id)
  283. return pricelist
  284. '''
  285. '''
  286. def compute_cart_item_price(self, price, currency_id, partner_id=None):
  287. from_currency = request.env.user.company_id.currency_id
  288. to_currency = request.env['res.currency'].search([('id', '=', currency_id)])
  289. return from_currency.compute(price, to_currency)
  290. '''
  291. '''
  292. def compute_cart_item_discount(self, price, product_id, currency_id):
  293. from_currency = request.env.user.company_id.currency_id
  294. to_currency = request.env['res.currency'].search([('id', '=', currency_id)])
  295. product = request.env['product.product'].search([('id', '=', product_id)])
  296. computed_price = from_currency.compute(price, to_currency)
  297. return 1.0 - (price / product.list_price)
  298. '''
  299. Create sale order from cart items values
  300. '''
  301. def create_sale_from_cart(self, partner_id, cart_items, date_confirm, currency_id, pricelist_id, payment_term_id=None):
  302. values = {
  303. 'partner_id': partner_id,
  304. 'order_line': [[0, False, {
  305. 'product_id': int(line.get('id')),
  306. 'product_uom_qty': float(line.get('quantity')),
  307. 'price_unit': self.compute_cart_item_price(float(line.get('price')), currency_id),
  308. 'discount': self.compute_cart_item_discount(float(line.get('price')), float(line.get('id')), currency_id)
  309. }] for line in cart_items],
  310. 'picking_policy': 'direct',
  311. 'date_confirm': date_confirm,
  312. 'currency_id': currency_id,
  313. 'pricelist_id': pricelist_id,
  314. 'payment_term': payment_term_id,
  315. 'state': 'draft',
  316. }
  317. return request.env['sale.order'].create(values)
  318. '''
  319. Confirm sale order
  320. '''
  321. def confirm_sale_order(self, sale_order_id):
  322. sale_order = request.env['sale.order'].browse(sale_order_id)
  323. sale_order.write({
  324. 'state': 'manual'
  325. })
  326. return sale_order.action_button_confirm()
  327. '''
  328. Create invoice from sale order
  329. '''
  330. def create_invoice(self, sale_order_id, currency_id, date_today):
  331. sale_order = request.env['sale.order'].browse(sale_order_id)
  332. invoice_id = sale_order.action_invoice_create()
  333. invoice = request.env['account.invoice'].browse(invoice_id)
  334. for picking in sale_order.picking_ids:
  335. picking.force_assign()
  336. picking.action_done()
  337. date_due = parse(date_today) + rd(days=max(invoice.payment_term.line_ids.mapped(lambda x: x.days + x.days2)))
  338. invoice.write({
  339. 'currency_id': currency_id,
  340. 'date_invoice': date_today,
  341. 'date_due': date_due.strftime(DEFAULT_SERVER_DATE_FORMAT),
  342. 'state': 'open'
  343. })
  344. return invoice
  345. '''
  346. Create move lines
  347. '''
  348. def create_invoice_move_lines(self, invoice_id, paid_amount, date_today):
  349. invoice = request.env['account.invoice'].browse(invoice_id)
  350. context = dict(request.context, lang=invoice.partner_id.lang)
  351. invoice_move_lines = invoice._get_analytic_lines()
  352. decimal_precision = request.env['decimal.precision'].precision_get('Account')
  353. compute_taxes = request.env['account.invoice.tax'].compute(invoice.with_context(context))
  354. invoice.check_tax_lines(compute_taxes)
  355. invoice._recompute_tax_amount()
  356. invoice_move_lines += request.env['account.invoice.tax'].move_line_get(invoice.id)
  357. total, total_currency, invoice_move_lines = invoice.with_context(context).compute_invoice_totals(invoice.company_id.currency_id, invoice.reference, invoice_move_lines)
  358. paid_amount = float_round(paid_amount, precision_digits=decimal_precision)
  359. paid_percentage = paid_amount / float_round(total_currency, precision_digits=decimal_precision)
  360. distributed_percentage = -(paid_percentage / len(invoice.payment_term.line_ids))
  361. diff_currency = invoice.currency_id != invoice.company_id.currency_id
  362. if diff_currency:
  363. paid_amount = invoice.currency_id.compute(paid_amount, invoice.company_id.currency_id)
  364. payment_lines = []
  365. for line in invoice.payment_term.line_ids:
  366. date_due = (parse(date_today) + rd(days=line.days + line.days2)).strftime(DEFAULT_SERVER_DATE_FORMAT)
  367. if paid_percentage and paid_percentage < 1.0:
  368. payment_lines.append([date_today, paid_percentage])
  369. paid_percentage = paid_amount = 0
  370. if date_due == date_today and line.value_amount:
  371. distributed_percentage = -((payment_lines[0][1] - line.value_amount) / (len(invoice.payment_term.line_ids) - 1))
  372. continue
  373. if line.value != 'balance':
  374. payment_lines.append([date_due, line.value_amount + distributed_percentage])
  375. continue
  376. payment_lines.append([date_due, line.value_amount])
  377. for payment_line in payment_lines:
  378. current_price = float_round(total * payment_line[1], precision_digits=decimal_precision)
  379. if current_price < 0.0:
  380. continue
  381. paid_amount += current_price
  382. # Compute move line price
  383. if payment_line[1]:
  384. price = current_price
  385. else:
  386. price = float_round(total - paid_amount, precision_digits=decimal_precision) or total
  387. # Compute move line amount in currency
  388. if diff_currency:
  389. amount_currency = invoice.company_id.currency_id.with_context(context).compute(price, invoice.currency_id)
  390. else:
  391. amount_currency = False
  392. # Create invoice move live value
  393. invoice_move_lines.append({
  394. 'type': 'dest',
  395. 'name': '/',
  396. 'price': price,
  397. 'account_id': invoice.account_id.id,
  398. 'date_maturity': payment_line[0],
  399. 'amount_currency': amount_currency,
  400. 'currency_id': diff_currency and invoice.currency_id.id,
  401. 'ref': invoice.reference
  402. })
  403. payment_lines = []
  404. return invoice_move_lines
  405. '''
  406. Create account move
  407. '''
  408. def create_account_move(self, invoice_id, invoice_move_lines):
  409. invoice = request.env['account.invoice'].browse(invoice_id)
  410. accounting_partner = request.env['res.partner']._find_accounting_partner(invoice.partner_id)
  411. move_line_values = [(0, 0, invoice.line_get_convert(line, accounting_partner.id, invoice.date_invoice)) for line in invoice_move_lines]
  412. move_line_values = invoice.group_lines(invoice_move_lines, move_line_values)
  413. move_line_values = invoice.finalize_invoice_move_lines(move_line_values)
  414. ctx = dict(request.context, lang=invoice.partner_id.lang, company_id=invoice.company_id.id)
  415. period = invoice.period_id
  416. if not period:
  417. period = period.with_context(ctx).find(invoice.date_invoice)[:1]
  418. if period:
  419. for line in move_line_values:
  420. line[2]['period_id'] = period.id
  421. ctx['invoice'] = invoice
  422. ctx_nolang = ctx.copy()
  423. ctx_nolang.pop('lang', None)
  424. account_move = request.env['account.move'].with_context(ctx_nolang).create({
  425. 'ref': invoice.reference or invoice.name,
  426. 'line_id': move_line_values,
  427. 'journal_id': invoice.journal_id.id,
  428. 'date': invoice.date_invoice,
  429. 'narration': invoice.comment,
  430. 'company_id': invoice.company_id.id,
  431. 'period_id': period.id
  432. })
  433. invoice.with_context(ctx).write({
  434. 'move_id': account_move.id,
  435. 'period_id': account_move.period_id.id,
  436. 'move_name': account_move.name,
  437. })
  438. account_move.post()
  439. return account_move
  440. '''
  441. Number to invoice
  442. '''
  443. def number_invoice(self, invoice_id):
  444. request.env['account.invoice'].browse(invoice_id).action_number()
  445. '''
  446. Create voucher
  447. '''
  448. def create_account_voucher(self, account_move_id, journal_id, currency_id, paid_amount):
  449. account_move = request.env['account.move'].browse(account_move_id)
  450. account_journal = request.env['account.journal'].browse(journal_id)
  451. account_voucher = request.env['account.voucher'].create({
  452. 'reference': account_move.name,
  453. 'type': 'receipt',
  454. 'journal_id': account_journal.id,
  455. 'company_id': account_move.company_id.id,
  456. 'pre_line': True,
  457. 'amount': paid_amount,
  458. 'period_id': account_move.period_id.id,
  459. 'date': account_move.date,
  460. 'partner_id': account_move.partner_id.id,
  461. 'account_id': account_journal.default_credit_account_id.id,
  462. 'currency_id': currency_id,
  463. 'line_cr_ids': [[0, False, {
  464. 'date_due': l.date_maturity,
  465. 'account_id': l.account_id.id,
  466. 'date_original': l.invoice.date_invoice,
  467. 'move_line_id': l.id,
  468. 'amount_original': abs(l.credit or l.debit or 0.0),
  469. 'amount_unreconciled': abs(l.amount_residual),
  470. 'amount': abs(l.debit) if account_move.date == l.date_maturity else 0.0,
  471. 'reconcile': account_move.date == l.date_maturity,
  472. 'currency_id': currency_id
  473. }] for l in account_move.line_id]
  474. })
  475. account_voucher.action_move_line_create()
  476. return account_voucher
  477. '''
  478. Close a invoice
  479. '''
  480. def close_invoice(self, invoice_id):
  481. invoice = request.env['account.invoice'].browse(invoice_id)
  482. if invoice.residual == 0:
  483. invoice.write({
  484. 'state': 'paid'
  485. })
  486. '''
  487. Create account bank statement lines
  488. '''
  489. def create_bank_statement_lines(self, account_voucher_id, reference=None):
  490. account_voucher = request.env['account.voucher'].browse(account_voucher_id)
  491. return [[0, False, {
  492. 'name': account_voucher.reference,
  493. 'amount': account_voucher.amount,
  494. 'partner_id': account_voucher.partner_id.id,
  495. 'voucher_id': account_voucher.id,
  496. 'journal_id': account_voucher.journal_id.id,
  497. 'account_id': account_voucher.account_id.id,
  498. 'journal_entry_id': account_voucher.move_id.id,
  499. 'currency_id': account_voucher.currency_id.id,
  500. 'ref': 'POS/' + (reference or '')
  501. }]]
  502. '''
  503. Create account bank statement
  504. '''
  505. def create_bank_statement(self, account_voucher_id, account_bank_statement_lines, date_today):
  506. account_voucher = request.env['account.voucher'].browse(account_voucher_id)
  507. account_bank_statement = request.env['account.bank.statement'].search([('journal_id', '=', account_voucher.journal_id.id), ('date', '=', date_today)])
  508. account_bank_statement_values = {
  509. 'date': date_today,
  510. 'user_id': request.env.user.id,
  511. 'journal_id': account_voucher.journal_id.id,
  512. 'period_id': account_voucher.period_id.id,
  513. 'line_ids': account_bank_statement_lines,
  514. 'state': 'open' if account_voucher.journal_id.type == 'cash' else 'draft'
  515. }
  516. if account_bank_statement:
  517. size = len(account_bank_statement)
  518. if size == 1:
  519. account_bank_statement.write(account_bank_statement_values)
  520. else:
  521. account_bank_statement[size - 1].write(account_bank_statement_values)
  522. else:
  523. account_bank_statement.create(account_bank_statement_values)
  524. return account_bank_statement
  525. '''
  526. '''
  527. def create_bank_payment_statement(self):
  528. pass
  529. '''
  530. New purchase resource route
  531. '''
  532. @http.route('/eiru_sales/init', auth='user', methods=['GET'], cors='*')
  533. def init_sale(self, **kw):
  534. self.make_info_log('Sending JSON response')
  535. settings = self.get_pos_settings()
  536. return self.make_gzip_response(
  537. {
  538. 'settings': settings,
  539. 'date': self.get_server_datetime(),
  540. 'user': self.get_user(),
  541. 'currencies': self.get_currencies_from_journals(),
  542. 'journals': self.get_journals(),
  543. 'customers': self.get_customers(image_type=settings.get('imageType')),
  544. 'products': self.get_products(image_type=settings.get('imageType')),
  545. 'paymentTerms': self.get_payment_terms(),
  546. 'banks': self.get_banks(),
  547. 'bankPaymentTypes': self.get_bank_payment_types(),
  548. 'chequeTypes': self.get_cheque_types()
  549. }
  550. )
  551. '''
  552. Get products data only
  553. '''
  554. @http.route('/eiru_sales/get_images', auth='user', methods=['GET'], cors='*')
  555. def get_images_only(self, **kw):
  556. settings = self.get_pos_settings()
  557. image_type = str(settings.get('imageType'))
  558. return self.make_gzip_response(
  559. {
  560. 'customers': self.get_customers(image_type=image_type),
  561. 'products': self.get_products(image_type=image_type)
  562. }
  563. )
  564. '''
  565. Create customer and return data
  566. '''
  567. @http.route('/eiru_sales/create_customer', type='json', auth='user', methods=['POST'], cors='*')
  568. def create_customer(self, **kw):
  569. self.make_info_log('Creating customer')
  570. customer = request.env['res.partner'].create({
  571. 'name': kw.get('name'),
  572. 'ruc': kw.get('ruc'),
  573. 'mobile': kw.get('mobile'),
  574. 'customer': True
  575. })
  576. return {
  577. 'id': customer.id,
  578. 'name': customer.display_name,
  579. 'image': customer.image_small,
  580. 'ruc': customer.ruc or None,
  581. 'phone': customer.phone or None,
  582. 'mobile': customer.mobile or None,
  583. 'email': customer.email or None
  584. }
  585. '''
  586. Save settings
  587. '''
  588. @http.route('/eiru_sales/save_settings', type='json', auth='user', methods=['POST'], cors='*')
  589. def save_settings(self, **kw):
  590. self.make_info_log('save settings')
  591. values = {}
  592. if kw.get('setting') == 'imageType':
  593. values['image_type'] = ('big', 'small')[kw.get('value', False)]
  594. if kw.get('setting') == 'allowCurrencyExchange':
  595. values['allow_currency_exchange'] = kw.get('value', False)
  596. if kw.get('setting') == 'viewCurrencyExchanges':
  597. values['view_currency_exchanges'] = kw.get('value', False)
  598. settings = request.env['base.config.settings'].search([], limit=1, order='id desc')
  599. settings.write(values)
  600. settings.execute()
  601. return self.get_pos_settings()
  602. '''
  603. Create product and return data
  604. '''
  605. @http.route('/eiru_sales/create_product', type='json', auth='user', methods=['POST'], cors='*')
  606. def create_product(self, **kw):
  607. self.make_info_log('Creating customer')
  608. product = request.env['product.template'].create({
  609. 'name': kw.get('name'),
  610. 'listPrice': float(kw.get('price')),
  611. 'ean13': kw.get('ean13')
  612. })
  613. return {
  614. 'id': product.id,
  615. 'name': product.display_name,
  616. 'ean13': product.ean13,
  617. 'image': product.image_small,
  618. 'listPrice': product.list_price,
  619. 'variantCount': product.product_variant_count,
  620. 'quantity': 1,
  621. 'price': product.list_price,
  622. 'discount': 0,
  623. 'variants': [{
  624. 'id': variant.id,
  625. 'name': variant.display_name,
  626. 'ean13': variant.ean13,
  627. 'image': variant.image_small,
  628. 'listPrice': variant.list_price,
  629. 'quantity': 1,
  630. 'price': variant.list_price,
  631. 'discount': 0,
  632. } for variant in product.product_variant_ids if variant.active]
  633. }
  634. '''
  635. Process sale
  636. '''
  637. @http.route('/eiru_sales/process_sale', type='json', auth='user', methods=['POST'], cors='*')
  638. def process_sale(self, **kw):
  639. self.make_info_log('Processing sale...')
  640. # Get date
  641. date_now = datetime.now(self.get_timezone()).strftime(DEFAULT_SERVER_DATE_FORMAT)
  642. self.make_info_log('[OK] Getting date')
  643. # Get currency
  644. currency_id = self.get_currency(kw.get('journalId'))
  645. self.make_info_log('[OK] Getting journal')
  646. # Get Pricelist
  647. pricelist = self.get_pricelist(currency_id)
  648. self.make_info_log('[OK] Getting product pricelist')
  649. # Create sale order
  650. sale_order = self.create_sale_from_cart(kw.get('customerId'), kw.get('items'), date_now, currency_id, pricelist.id, kw.get('paymentTermId'))
  651. self.make_info_log('[OK] Creating sale order')
  652. # Check if budget
  653. if kw.get('mode', 'sale') != 'sale':
  654. return {
  655. 'process': True
  656. }
  657. # Confirm sale
  658. self.confirm_sale_order(sale_order.id)
  659. self.make_info_log('[OK] Confirm sale order')
  660. # Create invoice
  661. invoice = self.create_invoice(sale_order.id, currency_id, date_now)
  662. self.make_info_log('[OK] Creating invoice')
  663. # Create invoice move lines
  664. invoice_move_lines = self.create_invoice_move_lines(invoice.id, float(kw.get('payment')), date_now)
  665. self.make_info_log('[OK] Creating invoice move lines')
  666. # Create account move
  667. account_move = self.create_account_move(invoice.id, invoice_move_lines)
  668. self.make_info_log('[OK] Creating account move')
  669. # Number invoice
  670. self.number_invoice(invoice.id)
  671. self.make_info_log('[OK] Number invoice')
  672. # Create account voucher
  673. account_voucher = self.create_account_voucher(account_move.id, kw.get('journalId'), currency_id, float(kw.get('payment')))
  674. self.make_info_log('[OK] Creating account voucher')
  675. # Close invoice
  676. self.close_invoice(invoice.id)
  677. self.make_info_log('[OK] Closing invoice')
  678. # Create account bank statement lines
  679. account_bank_statement_lines = self.create_bank_statement_lines(account_voucher.id)
  680. self.make_info_log('[OK] Creating account bank statement lines')
  681. # Create bank statement
  682. self.create_bank_statement(account_voucher.id, account_bank_statement_lines, date_now)
  683. self.make_info_log('[OK] Creating account bank statement')
  684. return {
  685. 'process': True,
  686. 'name': sale_order.display_name,
  687. 'date': self.get_server_datetime()
  688. }