summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafi Zadanly <zadanlyr@gmail.com>2023-02-13 10:41:41 +0700
committerRafi Zadanly <zadanlyr@gmail.com>2023-02-13 10:41:41 +0700
commitcfa0aa5c242b14332f7bc970bb65f1fbde0a9f3b (patch)
tree91f855964cadb0c76094cd2cc6b51f7994ce0c6d
parentfb04f8f3c533740c79c130ab4bc097b8529cae8e (diff)
parent7478616937cff56ccb994138831f90eae904e724 (diff)
fix conflict
-rw-r--r--indoteknik_api/controllers/api_v1/download.py46
-rw-r--r--indoteknik_api/controllers/api_v1/sale_order.py98
-rw-r--r--indoteknik_api/controllers/controller.py2
-rw-r--r--indoteknik_api/models/account_move.py4
-rw-r--r--indoteknik_api/models/rest_api.py32
-rw-r--r--indoteknik_api/models/sale_order.py2
-rw-r--r--indoteknik_custom/models/account_move.py13
-rwxr-xr-xindoteknik_custom/models/user_activity_log.py68
-rw-r--r--indoteknik_custom/views/dunning_run.xml13
-rwxr-xr-xindoteknik_custom/views/user_activity_log.xml21
10 files changed, 278 insertions, 21 deletions
diff --git a/indoteknik_api/controllers/api_v1/download.py b/indoteknik_api/controllers/api_v1/download.py
index 36f775b5..d9353896 100644
--- a/indoteknik_api/controllers/api_v1/download.py
+++ b/indoteknik_api/controllers/api_v1/download.py
@@ -1,7 +1,6 @@
from .. import controller
from odoo import http
from odoo.http import request
-import base64
class Download(controller.Controller):
@@ -13,22 +12,41 @@ class Download(controller.Controller):
('res_field', '=', field),
('res_id', '=', id),
], ['datas', 'mimetype'])
- return result if len(result) > 0 else None
+ return result[0] if len(result) > 0 else None
- @http.route(PREFIX + 'download/invoice/<id>', auth='none', method=['GET'])
- def download_invoice(self, **kw):
- id = int(kw.get('id', 0))
- return request.render('account.report_invoice', {'id': id})
+ @http.route(PREFIX + 'download/invoice/<id>/<token>', auth='none', method=['GET'])
+ def download_invoice(self, id, token):
+ id = int(id)
+
+ rest_api = request.env['rest.api']
+ md5_valid = rest_api.md5_salt_valid(id, 'account.move', token)
+ if not md5_valid:
+ return self.response('Unauthorized')
+
+ account_move = request.env['account.move'].sudo().search_read([('id', '=', id)], ['name'])
+ pdf, type = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'account.report_invoice')])._render_qweb_pdf([id])
+ return rest_api.response_attachment({
+ 'content': pdf,
+ 'mimetype': 'application/pdf',
+ 'filename': account_move[0]['name']
+ })
@http.route(PREFIX + 'download/tax-invoice/<id>/<token>', auth='none', method=['GET'])
def download_tax_invoice(self, id, token):
id = int(id)
- md5_by_id = request.env['rest.api'].md5_salt(id, 'account.move')
- if md5_by_id == token:
- attachment = self._get_attachment('account.move', 'efaktur_document', id)
- if attachment:
- return request.make_response(base64.b64decode(attachment['datas']), [('Content-Type', attachment['mimetype'])])
- return self.response('Dokumen tidak ditemukan', code=404)
-
- return self.response('Tidak diizinkan')
+ rest_api = request.env['rest.api']
+ md5_valid = rest_api.md5_salt_valid(id, 'account.move', token)
+ if not md5_valid:
+ return self.response('Unauthorized')
+
+ account_move = request.env['account.move'].sudo().search_read([('id', '=', id)], ['name'])
+ attachment = self._get_attachment('account.move', 'efaktur_document', id)
+ if attachment and len(account_move) > 0:
+ return rest_api.response_attachment({
+ 'content': attachment['datas'],
+ 'decode_content': True,
+ 'mimetype': attachment['mimetype'],
+ 'filename': account_move[0]['name'],
+ })
+ return self.response('Dokumen tidak ditemukan', code=404)
diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py
index 57a933f9..5f888e6c 100644
--- a/indoteknik_api/controllers/api_v1/sale_order.py
+++ b/indoteknik_api/controllers/api_v1/sale_order.py
@@ -3,6 +3,7 @@ from odoo import http
from odoo.http import request
import json
+
class SaleOrder(controller.Controller):
prefix = '/api/v1/'
PREFIX_PARTNER = prefix + 'partner/<partner_id>/'
@@ -119,7 +120,7 @@ class SaleOrder(controller.Controller):
return self.unauthorized_response()
if not params['valid']:
return self.response(code=400, description=params)
-
+
partner_child_ids = self.get_partner_child_ids(params['value']['partner_id'])
domain = [
('id', '=', params['value']['id']),
@@ -133,6 +134,101 @@ class SaleOrder(controller.Controller):
return self.response(data)
+ @http.route(PREFIX_PARTNER + 'sale_order/<id>/upload_po', auth='public', method=['POST', 'OPTIONS'], csrf=False)
+ def partner_upload_po_sale_order(self, **kw):
+ user_token = self.authenticate()
+ if not user_token:
+ return self.unauthorized_response()
+
+ params = self.get_request_params(kw, {
+ 'partner_id': ['number'],
+ 'id': ['number'],
+ 'name': [],
+ 'file': []
+ })
+ if not user_token['partner_id'] == params['value']['partner_id']:
+ return self.unauthorized_response()
+ if not params['valid']:
+ return self.response(code=400, description=params)
+ partner_child_ids = self.get_partner_child_ids(params['value']['partner_id'])
+ domain = [
+ ('id', '=', params['value']['id']),
+ ('partner_id', 'in', partner_child_ids)
+ ]
+ data = False
+ sale_order = request.env['sale.order'].search(domain)
+ if sale_order:
+ sale_order.partner_purchase_order_name = params['value']['name']
+ sale_order.partner_purchase_order_file = params['value']['file']
+ data = sale_order.id
+ return self.response(data)
+
+ @http.route(PREFIX_PARTNER + 'sale_order/<id>/download_po/<token>', auth='none', method=['GET'])
+ def partner_download_po_sale_order(self, id, token):
+ id = int(id)
+
+ rest_api = request.env['rest.api']
+ md5_valid = rest_api.md5_salt_valid(id, 'sale.order', token)
+ if not md5_valid:
+ return self.response('Unauthorized')
+
+ sale_order = request.env['sale.order'].sudo().search_read([('id', '=', id)], ['partner_purchase_order_name'])
+ attachment = rest_api.get_single_attachment('sale.order', 'partner_purchase_order_file', id)
+ if attachment and len(sale_order) > 0:
+ return rest_api.response_attachment({
+ 'content': attachment['datas'],
+ 'decode_content': True,
+ 'mimetype': attachment['mimetype'],
+ 'filename': sale_order[0]['partner_purchase_order_name']
+ })
+ return self.response('Dokumen tidak ditemukan', code=404)
+
+ @http.route(PREFIX_PARTNER + 'sale_order/<id>/download/<token>', auth='none', method=['GET'])
+ def partner_download_sale_order(self, id, token):
+ id = int(id)
+
+ rest_api = request.env['rest.api']
+ md5_valid = rest_api.md5_salt_valid(id, 'sale.order', token)
+ if not md5_valid:
+ return self.response('Unauthorized')
+
+ sale_order = request.env['sale.order'].sudo().search_read([('id', '=', id)], ['name'])
+ pdf, type = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'sale.report_saleorder')])._render_qweb_pdf([id])
+ if pdf and len(sale_order) > 0:
+ return rest_api.response_attachment({
+ 'content': pdf,
+ 'mimetype': 'application/pdf',
+ 'filename': sale_order[0]['name']
+ })
+ return self.response('Dokumen tidak ditemukan', code=404)
+
+ @http.route(PREFIX_PARTNER + 'sale_order/<id>/cancel', auth='public', method=['POST', 'OPTIONS'], csrf=False)
+ def partner_cancel_sale_order(self, **kw):
+ user_token = self.authenticate()
+ if not user_token:
+ return self.unauthorized_response()
+
+ params = self.get_request_params(kw, {
+ 'partner_id': ['number'],
+ 'id': ['number']
+ })
+ if not user_token['partner_id'] == params['value']['partner_id']:
+ return self.unauthorized_response()
+ if not params['valid']:
+ return self.response(code=400, description=params)
+
+ partner_child_ids = self.get_partner_child_ids(params['value']['partner_id'])
+ domain = [
+ ('id', '=', params['value']['id']),
+ ('partner_id', 'in', partner_child_ids)
+ ]
+ data = False
+ sale_order = request.env['sale.order'].search(domain)
+ if sale_order:
+ sale_order.state = 'cancel'
+ data = sale_order.id
+ return self.response(data)
+
@http.route(PREFIX_PARTNER + 'sale_order/checkout', auth='public', method=['POST', 'OPTIONS'], csrf=False)
def create_partner_sale_order(self, **kw):
user_token = self.authenticate()
diff --git a/indoteknik_api/controllers/controller.py b/indoteknik_api/controllers/controller.py
index c90d3ff1..59885148 100644
--- a/indoteknik_api/controllers/controller.py
+++ b/indoteknik_api/controllers/controller.py
@@ -86,6 +86,7 @@ class Controller(http.Controller):
return time
def response(self, data=[], code=200, description='OK'):
+ request.env['user.activity.log'].record_activity()
response = {
'status': {
'code': code,
@@ -149,4 +150,5 @@ class Controller(http.Controller):
def get_image(self, model, field, id):
model = request.env[model].sudo().search([('id', '=', id)], limit=1)
image = model[field] if model[field] else ''
+ request.env['user.activity.log'].record_activity()
return request.make_response(base64.b64decode(image), [('Content-Type', 'image/jpg')])
diff --git a/indoteknik_api/models/account_move.py b/indoteknik_api/models/account_move.py
index f77ded16..5c31f010 100644
--- a/indoteknik_api/models/account_move.py
+++ b/indoteknik_api/models/account_move.py
@@ -1,6 +1,5 @@
import datetime
from odoo import models
-import hashlib
class AccountMove(models.Model):
@@ -8,6 +7,7 @@ class AccountMove(models.Model):
def api_v1_single_response(self, account_move, context=False):
data = {
+ 'token': self.env['rest.api'].md5_salt(account_move.id, 'account.move'),
'id': account_move.id,
'name': account_move.name,
'purchase_order_name': account_move.ref or '',
@@ -16,7 +16,7 @@ class AccountMove(models.Model):
'amount_total': account_move.amount_total,
'amount_residual': account_move.amount_residual,
'invoice_date': '',
- 'efaktur_token': self.env['rest.api'].md5_salt(account_move.id, 'account.move') if account_move.efaktur_document else '',
+ 'efaktur': True if account_move.efaktur_document else False,
}
if isinstance(object, datetime.date):
data['invoice_date'] = account_move.invoice_date.strftime('%d/%m/%Y')
diff --git a/indoteknik_api/models/rest_api.py b/indoteknik_api/models/rest_api.py
index 052800b7..65119b52 100644
--- a/indoteknik_api/models/rest_api.py
+++ b/indoteknik_api/models/rest_api.py
@@ -1,7 +1,9 @@
from odoo import models
+from odoo.http import request
import datetime
from pytz import timezone
import hashlib
+import base64
class RestApi(models.TransientModel):
@@ -14,4 +16,32 @@ class RestApi(models.TransientModel):
return time
def md5_salt(self, value, salt):
- return hashlib.md5((salt + '$' + str(value)).encode()).hexdigest() \ No newline at end of file
+ return hashlib.md5((salt + '$' + str(value)).encode()).hexdigest()
+
+ def md5_salt_valid(self, value, salt, token):
+ return hashlib.md5((salt + '$' + str(value)).encode()).hexdigest() == token
+
+ def get_single_attachment(self, model, field, id):
+ domain = [
+ ('res_model', '=', model),
+ ('res_field', '=', field),
+ ('res_id', '=', id),
+ ]
+ fields = ['datas', 'mimetype']
+ result = self.env['ir.attachment'].sudo().search_read(domain, fields)
+ return result[0] if len(result) > 0 else None
+
+ def response_attachment(self, data = {}):
+ decode_content = data.get('decode_content', False)
+ if decode_content:
+ data['content'] = base64.b64decode(data['content'])
+
+ return request.make_response(
+ data['content'],
+ [
+ ('Content-Type', data['mimetype']),
+ ('Content-Disposition', 'attachment; filename=%s' % data['filename']),
+ ('Content-Length', len(data['content']))
+ ]
+ )
+ \ No newline at end of file
diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py
index afaf6ae6..7ce8ff61 100644
--- a/indoteknik_api/models/sale_order.py
+++ b/indoteknik_api/models/sale_order.py
@@ -6,11 +6,13 @@ class SaleOrder(models.Model):
def api_v1_single_response(self, sale_order, context=False):
data = {
+ 'token': self.env['rest.api'].md5_salt(sale_order.id, 'sale.order'),
'id': sale_order.id,
'name': sale_order.name,
'sales': sale_order.user_id.name,
'amount_total': sale_order.amount_total,
'purchase_order_name': sale_order.partner_purchase_order_name,
+ 'purchase_order_file': True if sale_order.partner_purchase_order_file else False,
'invoice_count': sale_order.invoice_count,
'status': 'draft',
}
diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py
index 1e0c56cf..54e51dcf 100644
--- a/indoteknik_custom/models/account_move.py
+++ b/indoteknik_custom/models/account_move.py
@@ -1,4 +1,5 @@
from odoo import models, api, fields
+from odoo.exceptions import AccessError, UserError, ValidationError
from datetime import timedelta
@@ -12,6 +13,18 @@ class AccountMove(models.Model):
date_terima_tukar_faktur = fields.Date(string='Terima Faktur')
shipper_faktur_id = fields.Many2one('delivery.carrier', string='Shipper Faktur')
+ def button_draft(self):
+ res = super(AccountMove, self).button_draft()
+ if not self.env.user.is_accounting:
+ raise UserError('Hanya Accounting yang bisa Reset to Draft')
+ return res
+
+ def action_post(self):
+ res = super(AccountMove, self).action_post()
+ if not self.env.user.is_accounting:
+ raise UserError('Hanya Accounting yang bisa Posting')
+ return res
+
@api.onchange('date_kirim_tukar_faktur')
def change_date_kirim_tukar_faktur(self):
for invoice in self:
diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py
index 32b389a1..9d9694af 100755
--- a/indoteknik_custom/models/user_activity_log.py
+++ b/indoteknik_custom/models/user_activity_log.py
@@ -1,6 +1,9 @@
-from odoo import models, fields
+from odoo import models, fields, api
+from odoo.http import request
from datetime import datetime, timedelta
import logging, re
+import requests
+import json
_logger = logging.getLogger(__name__)
@@ -11,11 +14,74 @@ class UserActivityLog(models.Model):
page_title = fields.Char(string="Judul Halaman")
url = fields.Char(string="URL")
+ ip_address = fields.Char('IP Address')
+ ip_address_lookup = fields.Text('IP Address Lookup')
+ ip_location_city = fields.Text('IP Location City')
+ ip_location_country = fields.Text('IP Location Country')
+ ip_location_country_code = fields.Text('IP Location Country Code')
+ ip_location_map = fields.Html('Embedded Map', compute='_compute_ip_location_map', sanitize=False)
res_user_id = fields.Many2one("res.users", string="User")
email = fields.Char(string="Email")
update_product = fields.Boolean(string="Update Product")
product_id = fields.Many2one('product.template', string='Product')
+ def _parse_json(self, json_string, key):
+ result = ''
+ if json_string:
+ json_object = json.loads(json_string)
+ if key in json_object:
+ result = json_object[key]
+ return result
+
+ def _compute_ip_location_map(self):
+ self.ip_location_map = ""
+ ip_location_lat = self._parse_json(self.ip_address_lookup, 'lat')
+ ip_location_lon = self._parse_json(self.ip_address_lookup, 'lon')
+ url = 'https://maps.google.com/maps?q=%s,%s&amp;hl=id&amp;z=15&amp;output=embed' % (ip_location_lat, ip_location_lon)
+ if ip_location_lat and ip_location_lon:
+ self.ip_location_map = "<iframe width='100%' height='500' frameborder='1' scrolling='no' src='"+ url +"'></iframe>"
+
+ def _parse_ip_location(self):
+ domain = [
+ ('ip_address_lookup', '!=', False),
+ ('ip_location_city', '=', False),
+ ('ip_location_country', '=', False),
+ ('ip_location_country_code', '=', False),
+ ]
+ logs = self.search(domain, limit=200, order='create_date asc')
+ for log in logs:
+ log.ip_location_city = self._parse_json(log.ip_address_lookup, 'city')
+ log.ip_location_country = self._parse_json(log.ip_address_lookup, 'country')
+ log.ip_location_country_code = self._parse_json(log.ip_address_lookup, 'countryCode')
+
+ def _load_ip_address_lookup(self):
+ domain = [
+ ('ip_address', '!=', False),
+ ('ip_address_lookup', '=', False),
+ ]
+ logs = self.search(domain, limit=100, order='create_date asc')
+ for log in logs:
+ try:
+ ipinfo = requests.get('http://ip-api.com/json/%s' % log.ip_address).json()
+ del ipinfo['status']
+ log.ip_address_lookup = json.dumps(ipinfo, indent=4, sort_keys=True)
+ except:
+ log.ip_address_lookup = ''
+ self._parse_ip_location()
+
+ def record_activity(self):
+ try:
+ httprequest = request.httprequest
+ if httprequest.remote_addr != '127.0.0.1':
+ self.env['user.activity.log'].sudo().create([{
+ 'page_title': request.env['ir.config_parameter'].get_param('web.base.url'),
+ 'url': httprequest.base_url,
+ 'ip_address': httprequest.remote_addr
+ }])
+ return True
+ except:
+ return False
+
def compile_product(self):
logs = self.env['user.activity.log'].search([
('email', '!=', False),
diff --git a/indoteknik_custom/views/dunning_run.xml b/indoteknik_custom/views/dunning_run.xml
index c251b206..6343a79b 100644
--- a/indoteknik_custom/views/dunning_run.xml
+++ b/indoteknik_custom/views/dunning_run.xml
@@ -82,10 +82,23 @@
</field>
</record>
+ <record id="view_dunning_run_filter" model="ir.ui.view">
+ <field name="name">dunning.run.list.select</field>
+ <field name="model">dunning.run</field>
+ <field name="priority" eval="15"/>
+ <field name="arch" type="xml">
+ <search string="Search Dunning Run">
+ <field name="number"/>
+ <field name="partner_id"/>
+ </search>
+ </field>
+ </record>
+
<record id="dunning_run_action" model="ir.actions.act_window">
<field name="name">Dunning Run</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">dunning.run</field>
+ <field name="search_view_id" ref="view_dunning_run_filter"/>
<field name="view_mode">tree,form</field>
</record>
diff --git a/indoteknik_custom/views/user_activity_log.xml b/indoteknik_custom/views/user_activity_log.xml
index db242505..b8792ee8 100755
--- a/indoteknik_custom/views/user_activity_log.xml
+++ b/indoteknik_custom/views/user_activity_log.xml
@@ -4,9 +4,10 @@
<field name="name">user.activity.log.tree</field>
<field name="model">user.activity.log</field>
<field name="arch" type="xml">
- <tree default_order="create_date desc">
+ <tree default_order="create_date desc" create="0" export_xlsx="0">
<field name="create_date"/>
<field name="page_title"/>
+ <field name="ip_address"/>
<field name="url" widget="url"/>
<field name="res_user_id"/>
<field name="email"/>
@@ -18,7 +19,7 @@
<field name="name">user.activity.log.form</field>
<field name="model">user.activity.log</field>
<field name="arch" type="xml">
- <form>
+ <form create="0" edit="0">
<sheet>
<group>
<group>
@@ -27,8 +28,24 @@
<field name="url" widget="url"/>
<field name="res_user_id"/>
<field name="email"/>
+ <field name="ip_address"/>
</group>
</group>
+ <notebook>
+ <page string="IP Lookup Detail">
+ <group>
+ <field name="ip_location_city"/>
+ <field name="ip_location_country"/>
+ <field name="ip_location_country_code"/>
+ </group>
+ </page>
+ <page string="IP Address Lookup">
+ <field name="ip_address_lookup"/>
+ </page>
+ <page string="IP Address Location">
+ <field name="ip_location_map" widget="html" />
+ </page>
+ </notebook>
</sheet>
</form>
</field>