From 46cc2c3deb299cc61c14a0675221b811aaf999b8 Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Fri, 27 Jan 2023 10:42:46 +0700 Subject: initial commit for midtrans development --- indoteknik_api/controllers/api_v1/__init__.py | 1 + indoteknik_api/controllers/api_v1/midtrans.py | 34 +++++++++++++++++++++++++ indoteknik_api/controllers/api_v1/sale_order.py | 2 +- indoteknik_custom/models/midtrans.py | 32 +++++++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 indoteknik_api/controllers/api_v1/midtrans.py create mode 100644 indoteknik_custom/models/midtrans.py diff --git a/indoteknik_api/controllers/api_v1/__init__.py b/indoteknik_api/controllers/api_v1/__init__.py index a4776503..ab499443 100644 --- a/indoteknik_api/controllers/api_v1/__init__.py +++ b/indoteknik_api/controllers/api_v1/__init__.py @@ -18,3 +18,4 @@ from . import wishlist from . import brand_homepage from . import customer from . import content +from . import midtrans diff --git a/indoteknik_api/controllers/api_v1/midtrans.py b/indoteknik_api/controllers/api_v1/midtrans.py new file mode 100644 index 00000000..9a0ca50e --- /dev/null +++ b/indoteknik_api/controllers/api_v1/midtrans.py @@ -0,0 +1,34 @@ +from .. import controller +from odoo import http +from odoo.http import request +import json + + +class Midtrans(controller.Controller): + prefix = '/api/v1/' + + @http.route(prefix + 'midtrans/notification', auth='none', type='json', csrf=False, cors='*', methods=['POST', 'OPTIONS']) + def notification(self, **kw): + json_raw = json.loads(request.httprequest.data) + trx_status = json.loads(request.httprequest.data)['transaction_status'] + order_no = json.loads(request.httprequest.data)['order_id'] + + query = [('name', '=', order_no)] + order = request.env['sale.order'].search(query, limit=1) + order.transaction_status = trx_status + + request.env['midtrans.notification'].create([{ + 'sale_order_id': order.id, + 'json_raw': json_raw, + 'payment_status': trx_status, + }]) + + return + + @http.route(prefix + 'midtrans/recurring', auth='none', type='json', csrf=False, cors='*', methods=['POST', 'OPTIONS']) + def recurring(self, **kw): + json_raw = json.loads(request.httprequest.data) + request.env['midtrans.recurring'].create([{ + 'json_raw': json_raw, + }]) + return diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index f2ec8dfe..4128d9f9 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -142,7 +142,7 @@ class SaleOrder(controller.Controller): 'partner_purchase_order_file': params['value']['po_file'] } sale_order = request.env['sale.order'].create([[parameters]]) - + var = json.loads(kw.get('transaction_time', '{}')) order_line = json.loads(params['value']['order_line']) parameters = [] for line in order_line: diff --git a/indoteknik_custom/models/midtrans.py b/indoteknik_custom/models/midtrans.py new file mode 100644 index 00000000..9546ff64 --- /dev/null +++ b/indoteknik_custom/models/midtrans.py @@ -0,0 +1,32 @@ +from odoo import fields, models, api +import logging + +_logger = logging.getLogger(__name__) + + +class MidtransNotification(models.Model): + _name = 'midtrans.notification' + + json_raw = fields.Char(string='JSON Raw Text') + sale_order_id = fields.Many2one('sale.order', string='Sales Order') + payment_status = fields.Selection([ + ('pending', 'Pending'), + ('capture', 'Capture'), + ('settlement', 'Settlement'), + ('deny', 'Deny'), + ('cancel', 'Cancel'), + ('expire', 'Expire'), + ('failure', 'Failure'), + ('refund', 'Refund'), + ('chargeback', 'Chargeback'), + ('partial_refund', 'Partial Refund'), + ('partial_chargeback', 'Partial Chargeback'), + ('authorize', 'Authorize'), + ], string='Payment Status', + help='Payment Gateway Status / Midtrans / Web, https://docs.midtrans.com/en/after-payment/status-cycle') + + +class MidtransRecurring(models.Model): + _name = 'midtrans.recurring' + + json_raw = fields.Char(string='JSON Raw Text') \ No newline at end of file -- cgit v1.2.3 From 669b9de298ed3667fc6aaf1e6070604c1799a0a8 Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Fri, 27 Jan 2023 10:56:07 +0700 Subject: bug fix unauthorized sale order --- indoteknik_api/controllers/api_v1/midtrans.py | 4 ++-- indoteknik_custom/models/__init__.py | 1 + indoteknik_custom/security/ir.model.access.csv | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/midtrans.py b/indoteknik_api/controllers/api_v1/midtrans.py index 9a0ca50e..a5e667cf 100644 --- a/indoteknik_api/controllers/api_v1/midtrans.py +++ b/indoteknik_api/controllers/api_v1/midtrans.py @@ -14,8 +14,8 @@ class Midtrans(controller.Controller): order_no = json.loads(request.httprequest.data)['order_id'] query = [('name', '=', order_no)] - order = request.env['sale.order'].search(query, limit=1) - order.transaction_status = trx_status + order = request.env['sale.order'].sudo().search(query, limit=1) + order.payment_status = trx_status request.env['midtrans.notification'].create([{ 'sale_order_id': order.id, diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index c6fb7d4f..121bd0f4 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -46,3 +46,4 @@ from . import x_partner_purchase_order from . import x_product_tags from . import website_ads from . import leads_monitoring +from . import midtrans diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index d469aa1e..c755c11a 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -27,4 +27,6 @@ access_website_content,access.website.content,model_website_content,,1,1,1,1 access_invoice_reklas,access.invoice.reklas,model_invoice_reklas,,1,1,1,1 access_custom_mail_marketing,access.custom.mail.marketing,model_custom_mail_marketing,,1,1,1,1 access_website_ads,access.website.ads,model_website_ads,,1,1,1,1 -access_leads_monitoring,access.leads.monitoring,model_leads_monitoring,,1,1,1,1 \ No newline at end of file +access_leads_monitoring,access.leads.monitoring,model_leads_monitoring,,1,1,1,1 +access_midtrans_notification,access.midtrans.notification,model_midtrans_notification,,1,1,1,1 +access_midtrans_recurring,access.midtrans.recurring,model_midtrans_recurring,,1,1,1,1 \ No newline at end of file -- cgit v1.2.3 From daf2b9581e8d1d72a72c7b01e760c4e67407472e Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Fri, 27 Jan 2023 11:05:53 +0700 Subject: add midtrans pay account notification --- indoteknik_api/controllers/api_v1/midtrans.py | 8 ++++++++ indoteknik_custom/models/midtrans.py | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/indoteknik_api/controllers/api_v1/midtrans.py b/indoteknik_api/controllers/api_v1/midtrans.py index a5e667cf..fdc801d3 100644 --- a/indoteknik_api/controllers/api_v1/midtrans.py +++ b/indoteknik_api/controllers/api_v1/midtrans.py @@ -32,3 +32,11 @@ class Midtrans(controller.Controller): 'json_raw': json_raw, }]) return + + @http.route(prefix + 'midtrans/payaccount', auth='none', type='json', csrf=False, cors='*', methods=['POST', 'OPTIONS']) + def payaccount(self, **kw): + json_raw = json.loads(request.httprequest.data) + request.env['midtrans.account'].create([{ + 'json_raw': json_raw, + }]) + return \ No newline at end of file diff --git a/indoteknik_custom/models/midtrans.py b/indoteknik_custom/models/midtrans.py index 9546ff64..76dee447 100644 --- a/indoteknik_custom/models/midtrans.py +++ b/indoteknik_custom/models/midtrans.py @@ -29,4 +29,10 @@ class MidtransNotification(models.Model): class MidtransRecurring(models.Model): _name = 'midtrans.recurring' - json_raw = fields.Char(string='JSON Raw Text') \ No newline at end of file + json_raw = fields.Char(string='JSON Raw Text') + + +class MidtransAccount(models.Model): + _name = 'midtrans.account' + + json_raw = fields.Char(string='JSON Raw Text') -- cgit v1.2.3 From 5ddf58175a447ecf728025c8615262a423f1313a Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Fri, 27 Jan 2023 11:07:25 +0700 Subject: add security for midtrans pay account --- indoteknik_custom/security/ir.model.access.csv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index c755c11a..83d9e2ed 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -29,4 +29,5 @@ access_custom_mail_marketing,access.custom.mail.marketing,model_custom_mail_mark access_website_ads,access.website.ads,model_website_ads,,1,1,1,1 access_leads_monitoring,access.leads.monitoring,model_leads_monitoring,,1,1,1,1 access_midtrans_notification,access.midtrans.notification,model_midtrans_notification,,1,1,1,1 -access_midtrans_recurring,access.midtrans.recurring,model_midtrans_recurring,,1,1,1,1 \ No newline at end of file +access_midtrans_recurring,access.midtrans.recurring,model_midtrans_recurring,,1,1,1,1 +access_midtrans_account,access.midtrans.account,model_midtrans_account,,1,1,1,1 \ No newline at end of file -- cgit v1.2.3 From 39e27d0187d352dfea7db1bc1c9aece42e348caa Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Fri, 27 Jan 2023 11:08:02 +0700 Subject: sale order and invoice api --- indoteknik_api/controllers/api_v1/invoice.py | 25 ++++++----------------- indoteknik_api/controllers/api_v1/sale_order.py | 27 ++++++------------------- indoteknik_api/controllers/controller.py | 3 --- indoteknik_api/models/__init__.py | 1 + indoteknik_api/models/account_move.py | 23 ++++++++++++++++++++- indoteknik_api/models/rest_api.py | 13 ++++++++++++ indoteknik_api/models/sale_order.py | 25 +++++++++++++++++++++-- 7 files changed, 71 insertions(+), 46 deletions(-) create mode 100644 indoteknik_api/models/rest_api.py diff --git a/indoteknik_api/controllers/api_v1/invoice.py b/indoteknik_api/controllers/api_v1/invoice.py index 5a6e8316..59cacfc4 100644 --- a/indoteknik_api/controllers/api_v1/invoice.py +++ b/indoteknik_api/controllers/api_v1/invoice.py @@ -34,7 +34,11 @@ class Invoice(controller.Controller): ] if params['value']['name']: name = params['value']['name'].replace(' ', '%') - domain.append(('name', 'ilike', '%'+ name +'%')) + domain += [ + '|', + ('name', 'ilike', '%'+ name +'%'), + ('ref', 'ilike', '%'+ name +'%') + ] invoices = request.env['account.move'].search(domain, offset=offset, limit=limit) data = { 'invoice_total': request.env['account.move'].search_count(domain), @@ -67,23 +71,6 @@ class Invoice(controller.Controller): data = {} account_move = request.env['account.move'].search(domain) if account_move: - res_users = request.env['res.users'] - data = { - 'id': account_move.id, - 'name': account_move.name, - 'purchase_order_name': account_move.ref or '', - 'payment_term': account_move.invoice_payment_term_id.name or '', - 'sales': account_move.invoice_user_id.name, - 'amount_total': account_move.amount_total, - 'amount_residual': account_move.amount_residual, - 'invoice_date': account_move.invoice_date.strftime('%d/%m/%Y') or '', - 'invoice_date_due': account_move.invoice_date_due.strftime('%d/%m/%Y') or '', - 'customer': res_users.api_address_response(account_move.partner_id), - 'products': [], - } - for line in account_move.invoice_line_ids: - product = request.env['product.product'].api_single_response(line.product_id) - product['quantity'] = line.quantity - data['products'].append(product) + data = request.env['account.move'].api_v1_single_response(account_move, context='with_detail') return self.response(data) diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 90dee56c..073f6301 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -30,7 +30,11 @@ class SaleOrder(controller.Controller): domain = [('partner_id', 'in', partner_child_ids)] if params['value']['name']: name = params['value']['name'].replace(' ', '%') - domain.append(('name', 'ilike', '%'+ name +'%')) + domain += [ + '|', + ('name', 'ilike', '%'+ name +'%'), + ('partner_purchase_order_name', 'ilike', '%'+ name +'%') + ] sale_orders = request.env['sale.order'].search(domain, offset=offset, limit=limit) data = { 'sale_order_total': request.env['sale.order'].search_count(domain), @@ -61,26 +65,7 @@ class SaleOrder(controller.Controller): data = {} sale_order = request.env['sale.order'].search(domain) if sale_order: - res_users = request.env['res.users'] - data = { - 'id': sale_order.id, - 'name': sale_order.name, - 'payment_term': sale_order.payment_term_id.name or '', - 'sales': sale_order.user_id.name or '', - 'date_order': self.time_to_str(sale_order.date_order, '%d/%m/%Y %H:%M:%S'), - 'purchase_order_name': sale_order.partner_purchase_order_name, - 'products': [], - 'amount_total': sale_order.amount_total, - 'address': { - 'customer': res_users.api_address_response(sale_order.partner_id), - 'invoice': res_users.api_address_response(sale_order.partner_invoice_id), - 'shipping': res_users.api_address_response(sale_order.partner_shipping_id) - } - } - for line in sale_order.order_line: - product = request.env['product.product'].api_single_response(line.product_id) - product['quantity'] = line.product_uom_qty - data['products'].append(product) + data = request.env['sale.order'].api_v1_single_response(sale_order, context='with_detail') return self.response(data) diff --git a/indoteknik_api/controllers/controller.py b/indoteknik_api/controllers/controller.py index a1a81e37..0b08a58f 100644 --- a/indoteknik_api/controllers/controller.py +++ b/indoteknik_api/controllers/controller.py @@ -7,11 +7,8 @@ from odoo import http from odoo.http import request from odoo.tools.config import config from pytz import timezone -import logging import jwt -_logger = logging.getLogger(__name__) - class Controller(http.Controller): jwt_secret_key = "NTNv7j0TuYARvmNMmWXo6fKvM4o6nvaUi9ryX38ZHL1bkrnD1ObOQ8JAUmHCBq7Iy7otZcyAagBLHVKvvYaIpmMuxmARQ97jUVG16Jkpkp1wXOPsrF9zwew6TpczyHkHgX5EuLg2MeBuiTqJACs1J0apruOOJCggOtkjB4c" diff --git a/indoteknik_api/models/__init__.py b/indoteknik_api/models/__init__.py index 98d84a80..a4f7363a 100644 --- a/indoteknik_api/models/__init__.py +++ b/indoteknik_api/models/__init__.py @@ -4,6 +4,7 @@ from . import product_pricelist from . import product_product from . import product_template from . import res_users +from . import rest_api from . import sale_order from . import x_manufactures from . import website_content diff --git a/indoteknik_api/models/account_move.py b/indoteknik_api/models/account_move.py index 9fd6fb18..3f85a447 100644 --- a/indoteknik_api/models/account_move.py +++ b/indoteknik_api/models/account_move.py @@ -6,7 +6,7 @@ from pytz import timezone class AccountMove(models.Model): _inherit = 'account.move' - def api_v1_single_response(self, account_move): + def api_v1_single_response(self, account_move, context=False): data = { 'id': account_move.id, 'name': account_move.name, @@ -17,4 +17,25 @@ class AccountMove(models.Model): 'amount_residual': account_move.amount_residual, 'invoice_date': account_move.invoice_date.strftime('%d/%m/%Y') or '' } + if context: + if context == 'with_detail': + res_users = self.env['res.users'] + data_with_detail = { + 'id': account_move.id, + 'name': account_move.name, + 'purchase_order_name': account_move.ref or '', + 'payment_term': account_move.invoice_payment_term_id.name or '', + 'sales': account_move.invoice_user_id.name, + 'amount_total': account_move.amount_total, + 'amount_residual': account_move.amount_residual, + 'invoice_date': account_move.invoice_date.strftime('%d/%m/%Y') or '', + 'invoice_date_due': account_move.invoice_date_due.strftime('%d/%m/%Y') or '', + 'customer': res_users.api_address_response(account_move.partner_id), + 'products': [], + } + for line in account_move.invoice_line_ids: + product = self.env['product.product'].api_single_response(line.product_id) + product['quantity'] = line.quantity + data_with_detail['products'].append(product) + data.update(data_with_detail) return data diff --git a/indoteknik_api/models/rest_api.py b/indoteknik_api/models/rest_api.py new file mode 100644 index 00000000..35cce201 --- /dev/null +++ b/indoteknik_api/models/rest_api.py @@ -0,0 +1,13 @@ +from odoo import models +import datetime +from pytz import timezone + + +class RestApi(models.TransientModel): + _name = 'rest.api' + + def datetime_to_str(self, object, format): + time = '' + if isinstance(object, datetime.datetime): + time = object.astimezone(timezone('Asia/Jakarta')).strftime(format) + return time \ No newline at end of file diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index 3359ee6a..aa20ccdb 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -4,11 +4,32 @@ from odoo import models class SaleOrder(models.Model): _inherit = 'sale.order' - def api_v1_single_response(self, sale_order): + def api_v1_single_response(self, sale_order, context=False): data = { 'id': sale_order.id, 'name': sale_order.name, 'sales': sale_order.user_id.name, - 'amount_total': sale_order.amount_total + 'amount_total': sale_order.amount_total, + 'purchase_order_name': sale_order.partner_purchase_order_name, + 'invoice_count': sale_order.invoice_count } + if context: + if context == 'with_detail': + res_users = self.env['res.users'] + data_with_detail = { + 'payment_term': sale_order.payment_term_id.name or '', + 'date_order': self.env['rest.api'].datetime_to_str(sale_order.date_order, '%d/%m/%Y %H:%M:%S'), + 'products': [], + 'address': { + 'customer': res_users.api_address_response(sale_order.partner_id), + 'invoice': res_users.api_address_response(sale_order.partner_invoice_id), + 'shipping': res_users.api_address_response(sale_order.partner_shipping_id) + }, + 'invoices': [self.env['account.move'].api_v1_single_response(x) for x in sale_order.invoice_ids] + } + for line in sale_order.order_line: + product = self.env['product.product'].api_single_response(line.product_id) + product['quantity'] = line.product_uom_qty + data_with_detail['products'].append(product) + data.update(data_with_detail) return data -- cgit v1.2.3 From 1ae31b80e82373cac0275daeb943f054296917af Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Fri, 27 Jan 2023 17:10:57 +0700 Subject: wishlist by user --- indoteknik_api/controllers/api_v1/wishlist.py | 63 +++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/indoteknik_api/controllers/api_v1/wishlist.py b/indoteknik_api/controllers/api_v1/wishlist.py index 9860f40b..192a9c49 100644 --- a/indoteknik_api/controllers/api_v1/wishlist.py +++ b/indoteknik_api/controllers/api_v1/wishlist.py @@ -5,6 +5,7 @@ from odoo.http import request class Wishlist(controller.Controller): prefix = '/api/v1/' + PREFIX_USER = prefix + 'user//' @http.route(prefix + 'wishlist', auth='public', methods=['GET']) def get_wishlist_by_user_id(self, **kw): @@ -71,3 +72,65 @@ class Wishlist(controller.Controller): create = request.env['website.user.wishlist'].create(params) result['id'] = create.id return self.response(result) + + @http.route(PREFIX_USER + 'wishlist', auth='public', methods=['GET', 'OPTIONS']) + def get_user_wishlist(self, **kw): + user_token = self.authenticate() + if not user_token: + return self.unauthorized_response() + + params = self.get_request_params(kw, { + 'user_id': ['number'], + 'product_id': [], + 'limit': ['default:0', 'number'], + 'offset': ['default:0', 'number'], + }) + limit = params['value']['limit'] + offset = params['value']['offset'] + if not user_token['id'] == params['value']['user_id']: + return self.unauthorized_response() + if not params['valid']: + return self.response(code=400, description=params) + + domain = [('user_id', '=', params['value']['user_id'])] + if params['value']['product_id']: + domain.append(('product_id', '=', params['value']['product_id'])) + wishlists = request.env['website.user.wishlist'].search(domain, limit=limit, offset=offset, order='create_date DESC') + product = [] + for wishlist in wishlists: + product.append(request.env['product.template'].api_single_response(wishlist.product_id)) + data = { + 'product_total': request.env['website.user.wishlist'].search_count(domain), + 'products': product + } + return self.response(data) + + @http.route(PREFIX_USER + 'wishlist/create-or-delete', auth='public', methods=['POST', 'OPTIONS'], csrf=False) + def create_or_delete_user_wishlist(self, **kw): + user_token = self.authenticate() + if not user_token: + return self.unauthorized_response() + + params = self.get_request_params(kw, { + 'user_id': ['number'], + 'product_id': ['required', 'number'], + }) + if not user_token['id'] == params['value']['user_id']: + return self.unauthorized_response() + if not params['valid']: + return self.response(code=400, description=params) + + query = [ + ('user_id', '=', params['value']['user_id']), + ('product_id', '=', params['value']['product_id']) + ] + wishlist = request.env['website.user.wishlist'].search(query, limit=1) + result = {} + if wishlist: + wishlist.unlink() + result['id'] = wishlist.id + else: + create = request.env['website.user.wishlist'].create(params['value']) + result['id'] = create.id + return self.response(result) + \ No newline at end of file -- cgit v1.2.3 From a197b978872cab655263541d65bc86e5131e78aa Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Mon, 30 Jan 2023 09:34:06 +0700 Subject: api wishlist --- indoteknik_api/controllers/api_v1/wishlist.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/wishlist.py b/indoteknik_api/controllers/api_v1/wishlist.py index 192a9c49..a3299033 100644 --- a/indoteknik_api/controllers/api_v1/wishlist.py +++ b/indoteknik_api/controllers/api_v1/wishlist.py @@ -81,7 +81,7 @@ class Wishlist(controller.Controller): params = self.get_request_params(kw, { 'user_id': ['number'], - 'product_id': [], + 'product_id': ['number'], 'limit': ['default:0', 'number'], 'offset': ['default:0', 'number'], }) @@ -92,7 +92,10 @@ class Wishlist(controller.Controller): if not params['valid']: return self.response(code=400, description=params) - domain = [('user_id', '=', params['value']['user_id'])] + domain = [ + ('user_id', '=', params['value']['user_id']), + ('variant_id', '=', False) + ] if params['value']['product_id']: domain.append(('product_id', '=', params['value']['product_id'])) wishlists = request.env['website.user.wishlist'].search(domain, limit=limit, offset=offset, order='create_date DESC') -- cgit v1.2.3 From 92db799e6902b2a2bd6aca5c95c4ec8e46f816de Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Tue, 31 Jan 2023 09:55:37 +0700 Subject: add product in sale order midtrans --- indoteknik_api/controllers/api_v1/sale_order.py | 27 ++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 7ce8cd43..77c3e233 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -9,6 +9,7 @@ class SaleOrder(controller.Controller): @http.route(prefix + "sale_order_number", auth='public', method=['GET', 'OPTIONS']) def get_number_sale_order(self, **kw): + # for midtrans only user_token = self.authenticate() if not user_token: return self.unauthorized_response() @@ -16,11 +17,31 @@ class SaleOrder(controller.Controller): sale_order_id = int(kw.get('sale_order_id', '0')) sale_number = str(kw.get('sale_number', '')) if sale_order_id > 0: - sales = request.env['sale.order'].search_read([('id', '=', sale_order_id)], fields=['id', 'name', 'amount_total', 'state']) + query = [('id', '=', sale_order_id)] + # sales = request.env['sale.order'].search_read([('id', '=', sale_order_id)], fields=['id', 'name', 'amount_total', 'state']) + sales = request.env['sale.order'].search(query, limit=1) else: - sales = request.env['sale.order'].search_read([('name', '=', sale_number)], fields=['id', 'name', 'amount_total', 'state']) + query = [('name', '=', sale_number)] + # sales = request.env['sale.order'].search_read([('name', '=', sale_number)], fields=['id', 'name', 'amount_total', 'state']) + sales = request.env['sale.order'].search(query, limit=1) + data = [] + for sale in sales: + product_name = '' + product_not_in_id = 0 + for line in sale.order_line: + product_name = line.product_id.name + product_not_in_id = line.product_id.id + break + data.append({ + 'id': sale.id, + 'name': sale.name, + 'amount_total': sale.amount_total, + 'state': sale.state, + 'product_name': product_name, + 'product_not_in_id': product_not_in_id, + }) - return self.response(sales) + return self.response(data) @http.route(PREFIX_PARTNER + 'sale_order', auth='public', method=['GET', 'OPTIONS']) def get_partner_sale_order(self, **kw): -- cgit v1.2.3 From 27a1a3d68f728455ae196d2aa5736858ba623d09 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 31 Jan 2023 13:57:05 +0700 Subject: api category tree --- indoteknik_api/controllers/api_v1/category.py | 49 +++++++++++++++++++++++++ indoteknik_api/controllers/api_v1/sale_order.py | 1 - indoteknik_api/models/sale_order.py | 17 ++++++++- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/category.py b/indoteknik_api/controllers/api_v1/category.py index 62faff85..b7ea65ed 100644 --- a/indoteknik_api/controllers/api_v1/category.py +++ b/indoteknik_api/controllers/api_v1/category.py @@ -7,6 +7,55 @@ import ast class Category(controller.Controller): prefix = '/api/v1/' + @http.route(prefix + 'category/child', auth='public', methods=['GET', 'OPTIONS']) + def get_category_child(self, **kw): + user_token = self.authenticate() + if not user_token: + return self.unauthorized_response() + + params = self.get_request_params(kw, { + 'parent_id': ['number', 'default:0'] + }) + if not params['valid']: + return self.response(code=400, description=params) + if params['value']['parent_id'] == 0: + params['value']['parent_id'] = False + + categories = request.env['product.public.category'].search_read([('parent_frontend_id', '=', params['value']['parent_id'])], ['id', 'name']) + return self.response(categories) + + @http.route(prefix + 'category/tree', auth='public', methods=['GET', 'OPTIONS']) + def get_category_tree(self, **kw): + user_token = self.authenticate() + if not user_token: + return self.unauthorized_response() + + parent_categories = request.env['product.public.category'].search_read([('parent_frontend_id', '=', False)], ['id', 'name']) + data = [] + for parent_category in parent_categories: + parent_data = { + 'id': parent_category['id'], + 'name': parent_category['name'], + 'childs': [] + } + child_1_categories = request.env['product.public.category'].search_read([('parent_frontend_id', '=', parent_category['id'])], ['id', 'name']) + for child_1_category in child_1_categories: + child_1_data = { + 'id': child_1_category['id'], + 'name': child_1_category['name'], + 'childs': [] + } + child_2_categories = request.env['product.public.category'].search_read([('parent_frontend_id', '=', child_1_category['id'])], ['id', 'name']) + for child_2_category in child_2_categories: + child_2_data = { + 'id': child_2_category['id'], + 'name': child_2_category['name'], + } + child_1_data['childs'].append(child_2_data) + parent_data['childs'].append(child_1_data) + data.append(parent_data) + return self.response(data) + @http.route(prefix + 'categories_homepage', auth='public', methods=['GET', 'OPTIONS']) def get_categories_homepage(self, **kw): if not self.authenticate(): diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 7ce8cd43..9b52e79a 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -127,7 +127,6 @@ class SaleOrder(controller.Controller): 'partner_purchase_order_file': params['value']['po_file'] } sale_order = request.env['sale.order'].create([[parameters]]) - var = json.loads(kw.get('transaction_time', '{}')) order_line = json.loads(params['value']['order_line']) parameters = [] for line in order_line: diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index aa20ccdb..826f2a14 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -11,8 +11,23 @@ class SaleOrder(models.Model): 'sales': sale_order.user_id.name, 'amount_total': sale_order.amount_total, 'purchase_order_name': sale_order.partner_purchase_order_name, - 'invoice_count': sale_order.invoice_count + 'invoice_count': sale_order.invoice_count, + 'status': 'draft', } + if sale_order.state == 'cancel': + data['status'] = 'cancel' + if sale_order.state in ['draft', 'sent']: + data['status'] = 'draft' + if sale_order.approval_status in ['pengajuan1', 'pengajuan2']: + data['status'] = 'waiting' + if sale_order.state == 'sale': + data['status'] = 'sale' + for picking in sale_order.picking_ids: + if picking.state == 'assigned': + data['status'] = 'shipping' + if sale_order.state == 'done': + data['status'] = 'done' + if context: if context == 'with_detail': res_users = self.env['res.users'] -- cgit v1.2.3 From cf289c9d54691a451937595e9695d02cf894cbb5 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 31 Jan 2023 16:18:31 +0700 Subject: categories_homepage image --- indoteknik_api/controllers/api_v1/category.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_api/controllers/api_v1/category.py b/indoteknik_api/controllers/api_v1/category.py index b7ea65ed..3a83f6a1 100644 --- a/indoteknik_api/controllers/api_v1/category.py +++ b/indoteknik_api/controllers/api_v1/category.py @@ -82,7 +82,7 @@ class Category(controller.Controller): 'sequence': category.sequence, 'category_id': category.category_id.id, 'name': category.category_id.name, - 'image': base_url + 'api/image/website.categories.homepage/image/' + str(category.id) if category.image else '', + 'image': request.env['ir.attachment'].api_image('website.categories.homepage', 'image', category.id), 'url': category.url, # 'brands': [y.x_name for y in brands], 'brands': [request.env['x_manufactures'].api_single_response(y) for y in brands], -- cgit v1.2.3 From 60e57d97be4033e43eca982ba833156e69a9cbf6 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Wed, 1 Feb 2023 09:11:19 +0700 Subject: api category --- indoteknik_api/controllers/api_v1/category.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/indoteknik_api/controllers/api_v1/category.py b/indoteknik_api/controllers/api_v1/category.py index 3a83f6a1..ff1baf6b 100644 --- a/indoteknik_api/controllers/api_v1/category.py +++ b/indoteknik_api/controllers/api_v1/category.py @@ -56,12 +56,24 @@ class Category(controller.Controller): data.append(parent_data) return self.response(data) + @http.route(prefix + 'categories_homepage/ids', auth='public', methods=['GET', 'OPTIONS']) + def get_categories_homepage_count(self, **kw): + if not self.authenticate(): + return self.response(code=401, description='Unauthorized') + query = [('status', '=', 'tayang')] + categories = request.env['website.categories.homepage'].search_read(query, ['id']) + return self.response([x['id'] for x in categories]) + + @http.route(prefix + 'categories_homepage', auth='public', methods=['GET', 'OPTIONS']) def get_categories_homepage(self, **kw): if not self.authenticate(): return self.response(code=401, description='Unauthorized') base_url = request.env['ir.config_parameter'].get_param('web.base.url') query = [('status', '=', 'tayang')] + id = kw.get('id') + if id: + query.append(('id', '=', id)) categories = request.env['website.categories.homepage'].search(query, order='sequence') data = [] for category in categories: -- cgit v1.2.3 From 06534703452ee4c3afbabd21e872d20b085badba Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Thu, 2 Feb 2023 14:20:17 +0700 Subject: fix error parse time to str on account_move --- indoteknik_api/models/account_move.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/indoteknik_api/models/account_move.py b/indoteknik_api/models/account_move.py index 3f85a447..c70c21a5 100644 --- a/indoteknik_api/models/account_move.py +++ b/indoteknik_api/models/account_move.py @@ -15,8 +15,10 @@ class AccountMove(models.Model): 'sales': account_move.invoice_user_id.name, 'amount_total': account_move.amount_total, 'amount_residual': account_move.amount_residual, - 'invoice_date': account_move.invoice_date.strftime('%d/%m/%Y') or '' + 'invoice_date': '' } + if isinstance(object, datetime.date): + data['invoice_date'] = account_move.invoice_date.strftime('%d/%m/%Y') if context: if context == 'with_detail': res_users = self.env['res.users'] -- cgit v1.2.3 From 6b97d72c91f9a36462d08027660dddab945db01c Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Thu, 2 Feb 2023 14:26:42 +0700 Subject: show invoice only in posted status --- indoteknik_api/models/sale_order.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index 826f2a14..c7d488be 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -40,11 +40,14 @@ class SaleOrder(models.Model): 'invoice': res_users.api_address_response(sale_order.partner_invoice_id), 'shipping': res_users.api_address_response(sale_order.partner_shipping_id) }, - 'invoices': [self.env['account.move'].api_v1_single_response(x) for x in sale_order.invoice_ids] + 'invoices': [] } for line in sale_order.order_line: product = self.env['product.product'].api_single_response(line.product_id) product['quantity'] = line.product_uom_qty data_with_detail['products'].append(product) + for invoice in sale_order.invoice_ids: + if invoice.state == 'posted': + data_with_detail['invoices'].append(self.env['account.move'].api_v1_single_response(invoice)) data.update(data_with_detail) return data -- cgit v1.2.3 From 3d402f5a12d50d2264dde918d4b893b9c8943389 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Thu, 2 Feb 2023 17:12:04 +0700 Subject: download tax invoice --- indoteknik_api/controllers/api_v1/__init__.py | 1 + indoteknik_api/controllers/api_v1/download.py | 25 +++++++++++++++++++++++++ indoteknik_api/controllers/api_v1/sale_order.py | 5 ++++- indoteknik_api/models/account_move.py | 5 +++-- indoteknik_api/models/rest_api.py | 6 +++++- 5 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 indoteknik_api/controllers/api_v1/download.py diff --git a/indoteknik_api/controllers/api_v1/__init__.py b/indoteknik_api/controllers/api_v1/__init__.py index ab499443..63540928 100644 --- a/indoteknik_api/controllers/api_v1/__init__.py +++ b/indoteknik_api/controllers/api_v1/__init__.py @@ -4,6 +4,7 @@ from . import cart from . import category from . import city from . import district +from . import download from . import flash_sale from . import invoice from . import manufacture diff --git a/indoteknik_api/controllers/api_v1/download.py b/indoteknik_api/controllers/api_v1/download.py new file mode 100644 index 00000000..b215a4cd --- /dev/null +++ b/indoteknik_api/controllers/api_v1/download.py @@ -0,0 +1,25 @@ +from .. import controller +from odoo import http +from odoo.http import request +import base64 + + +class Download(controller.Controller): + PREFIX = '/api/v1/' + + @http.route(PREFIX + 'download/tax-invoice//', auth='none', method=['GET']) + def download_tax_invoice(self, **kw): + id = int(kw.get('id', 0)) + token = kw.get('token', '') + + md5_by_id = request.env['rest.api'].md5_salt(id, 'account.move$') + if md5_by_id == token: + attachment = request.env['ir.attachment'].sudo().search_read([ + ('res_model', '=', 'account.move'), + ('res_field', '=', 'efaktur_document'), + ('res_id', '=', id), + ], ['datas', 'mimetype']) + attachment = attachment[0] + return request.make_response(base64.b64decode(attachment['datas']), [('Content-Type', attachment['mimetype'])]) + + return self.response('Tidak diizinkan') diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 11186605..52ccf9fa 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -121,6 +121,7 @@ class SaleOrder(controller.Controller): 'order_line': ['required', 'default:[]'], 'po_number': [], 'po_file': [], + 'type': [], }) if not user_token['partner_id'] == params['value']['partner_id']: @@ -145,8 +146,10 @@ class SaleOrder(controller.Controller): 'real_shipping_id': params['value']['partner_shipping_id'], 'partner_invoice_id': params['value']['partner_invoice_id'], 'partner_purchase_order_name': params['value']['po_number'], - 'partner_purchase_order_file': params['value']['po_file'] + 'partner_purchase_order_file': params['value']['po_file'], } + if params['value']['type'] == 'sale_order': + parameters['approval_status'] = 'pengajuan1' sale_order = request.env['sale.order'].create([[parameters]]) order_line = json.loads(params['value']['order_line']) parameters = [] diff --git a/indoteknik_api/models/account_move.py b/indoteknik_api/models/account_move.py index c70c21a5..5589b5fc 100644 --- a/indoteknik_api/models/account_move.py +++ b/indoteknik_api/models/account_move.py @@ -1,6 +1,6 @@ import datetime from odoo import models -from pytz import timezone +import hashlib class AccountMove(models.Model): @@ -15,7 +15,8 @@ class AccountMove(models.Model): 'sales': account_move.invoice_user_id.name, 'amount_total': account_move.amount_total, 'amount_residual': account_move.amount_residual, - 'invoice_date': '' + 'invoice_date': '', + 'efaktur_token': self.env['rest.api'].md5_salt(account_move.id, 'account.move$') if account_move.efaktur_document else '', } 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 35cce201..2c54769e 100644 --- a/indoteknik_api/models/rest_api.py +++ b/indoteknik_api/models/rest_api.py @@ -1,6 +1,7 @@ from odoo import models import datetime from pytz import timezone +import hashlib class RestApi(models.TransientModel): @@ -10,4 +11,7 @@ class RestApi(models.TransientModel): time = '' if isinstance(object, datetime.datetime): time = object.astimezone(timezone('Asia/Jakarta')).strftime(format) - return time \ No newline at end of file + return time + + def md5_salt(self, value, salt): + return hashlib.md5((salt + str(value)).encode()).hexdigest() \ No newline at end of file -- cgit v1.2.3 From 37329585403b7c47406234677fd1a844360284ff Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Fri, 3 Feb 2023 08:51:31 +0700 Subject: [FIX] controller function get_partner_child_ids --- indoteknik_api/controllers/controller.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/indoteknik_api/controllers/controller.py b/indoteknik_api/controllers/controller.py index 0b08a58f..c90d3ff1 100644 --- a/indoteknik_api/controllers/controller.py +++ b/indoteknik_api/controllers/controller.py @@ -135,10 +135,10 @@ class Controller(http.Controller): return False def get_partner_child_ids(self, partner_id): - parent_partner_id = request.env['res.partner'].search([('id', '=', partner_id)], limit=1) - parent_partner_id = parent_partner_id.parent_id.id or parent_partner_id.id - partner_childs = request.env['res.partner'].search([('parent_id', '=', int(parent_partner_id))]) - partner_child_ids = [v['id'] for v in partner_childs] + [partner_id] + partner = request.env['res.partner'].search([('id', '=', partner_id)], limit=1) + partner_child_ids = [x['id'] for x in partner.child_ids] + [partner.id] + if partner.parent_id: + partner_child_ids += [x['id'] for x in partner.parent_id.child_ids] return partner_child_ids @http.route('/api/token', auth='public', methods=['GET', 'OPTIONS']) -- cgit v1.2.3 From 9eb80e0aad8966c42fa721738986737b4040e0e4 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Fri, 3 Feb 2023 10:10:16 +0700 Subject: [ADD] feature download invoice --- indoteknik_api/controllers/api_v1/download.py | 31 +++++++++++++++++---------- indoteknik_api/models/account_move.py | 2 +- indoteknik_api/models/rest_api.py | 2 +- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/download.py b/indoteknik_api/controllers/api_v1/download.py index b215a4cd..36f775b5 100644 --- a/indoteknik_api/controllers/api_v1/download.py +++ b/indoteknik_api/controllers/api_v1/download.py @@ -7,19 +7,28 @@ import base64 class Download(controller.Controller): PREFIX = '/api/v1/' - @http.route(PREFIX + 'download/tax-invoice//', auth='none', method=['GET']) - def download_tax_invoice(self, **kw): + def _get_attachment(self, model, field, id): + result = request.env['ir.attachment'].sudo().search_read([ + ('res_model', '=', model), + ('res_field', '=', field), + ('res_id', '=', id), + ], ['datas', 'mimetype']) + return result if len(result) > 0 else None + + @http.route(PREFIX + 'download/invoice/', auth='none', method=['GET']) + def download_invoice(self, **kw): id = int(kw.get('id', 0)) - token = kw.get('token', '') + return request.render('account.report_invoice', {'id': id}) + + @http.route(PREFIX + 'download/tax-invoice//', 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$') + md5_by_id = request.env['rest.api'].md5_salt(id, 'account.move') if md5_by_id == token: - attachment = request.env['ir.attachment'].sudo().search_read([ - ('res_model', '=', 'account.move'), - ('res_field', '=', 'efaktur_document'), - ('res_id', '=', id), - ], ['datas', 'mimetype']) - attachment = attachment[0] - return request.make_response(base64.b64decode(attachment['datas']), [('Content-Type', attachment['mimetype'])]) + 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') diff --git a/indoteknik_api/models/account_move.py b/indoteknik_api/models/account_move.py index 5589b5fc..f77ded16 100644 --- a/indoteknik_api/models/account_move.py +++ b/indoteknik_api/models/account_move.py @@ -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_token': self.env['rest.api'].md5_salt(account_move.id, 'account.move') if account_move.efaktur_document else '', } 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 2c54769e..052800b7 100644 --- a/indoteknik_api/models/rest_api.py +++ b/indoteknik_api/models/rest_api.py @@ -14,4 +14,4 @@ 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() \ No newline at end of file -- cgit v1.2.3 From 8cb3d124ec96b78872ebd0d0c969564249f15671 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Fri, 3 Feb 2023 10:39:38 +0700 Subject: [FIX] feature download invoice --- indoteknik_api/controllers/api_v1/download.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/download.py b/indoteknik_api/controllers/api_v1/download.py index 36f775b5..38225b85 100644 --- a/indoteknik_api/controllers/api_v1/download.py +++ b/indoteknik_api/controllers/api_v1/download.py @@ -16,9 +16,10 @@ class Download(controller.Controller): return result if len(result) > 0 else None @http.route(PREFIX + 'download/invoice/', auth='none', method=['GET']) - def download_invoice(self, **kw): - id = int(kw.get('id', 0)) - return request.render('account.report_invoice', {'id': id}) + def download_invoice(self, id): + id = int(id) + data = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'account.report_invoice')])._render_qweb_pdf([id]) + return request.make_response(base64.b64decode(data[0]), [('Content-Type', 'application/pdf')]) @http.route(PREFIX + 'download/tax-invoice//', auth='none', method=['GET']) def download_tax_invoice(self, id, token): @@ -28,6 +29,7 @@ class Download(controller.Controller): if md5_by_id == token: attachment = self._get_attachment('account.move', 'efaktur_document', id) if attachment: + attachment = attachment[0] return request.make_response(base64.b64decode(attachment['datas']), [('Content-Type', attachment['mimetype'])]) return self.response('Dokumen tidak ditemukan', code=404) -- cgit v1.2.3 From 6b5f3041727d84db4d24215062940b8f2fca6d1c Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Fri, 3 Feb 2023 14:43:58 +0700 Subject: [FIX] feature download invoice --- indoteknik_api/controllers/api_v1/download.py | 28 ++++++++++++++++----------- indoteknik_api/models/account_move.py | 3 ++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/download.py b/indoteknik_api/controllers/api_v1/download.py index 38225b85..3794744e 100644 --- a/indoteknik_api/controllers/api_v1/download.py +++ b/indoteknik_api/controllers/api_v1/download.py @@ -15,22 +15,28 @@ class Download(controller.Controller): ], ['datas', 'mimetype']) return result if len(result) > 0 else None - @http.route(PREFIX + 'download/invoice/', auth='none', method=['GET']) - def download_invoice(self, id): + @http.route(PREFIX + 'download/invoice//', auth='none', method=['GET']) + def download_invoice(self, id, token): id = int(id) - data = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'account.report_invoice')])._render_qweb_pdf([id]) - return request.make_response(base64.b64decode(data[0]), [('Content-Type', 'application/pdf')]) + + md5_by_id = request.env['rest.api'].md5_salt(id, 'account.move') + if not md5_by_id == token: + return self.response('Unauthorized') + + pdf, type = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'account.report_invoice')])._render_qweb_pdf([id]) + return request.make_response(pdf, [('Content-Type', 'application/pdf')]) @http.route(PREFIX + 'download/tax-invoice//', 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: - attachment = attachment[0] - return request.make_response(base64.b64decode(attachment['datas']), [('Content-Type', attachment['mimetype'])]) - return self.response('Dokumen tidak ditemukan', code=404) + if not md5_by_id == token: + return self.response('Unauthorized') + + attachment = self._get_attachment('account.move', 'efaktur_document', id) + if attachment: + attachment = attachment[0] + 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') diff --git a/indoteknik_api/models/account_move.py b/indoteknik_api/models/account_move.py index f77ded16..3c8fd655 100644 --- a/indoteknik_api/models/account_move.py +++ b/indoteknik_api/models/account_move.py @@ -8,6 +8,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 +17,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') -- cgit v1.2.3 From 446e3be759d72b7a06b4e4671b91c6f9c8bfa903 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Mon, 6 Feb 2023 12:02:42 +0700 Subject: add api cancel SO and upload PO in SO --- indoteknik_api/controllers/api_v1/download.py | 8 ++-- indoteknik_api/controllers/api_v1/sale_order.py | 56 +++++++++++++++++++++++++ indoteknik_api/models/account_move.py | 1 - indoteknik_api/models/rest_api.py | 5 ++- indoteknik_api/models/sale_order.py | 1 + 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/download.py b/indoteknik_api/controllers/api_v1/download.py index 3794744e..f12be337 100644 --- a/indoteknik_api/controllers/api_v1/download.py +++ b/indoteknik_api/controllers/api_v1/download.py @@ -19,8 +19,8 @@ class Download(controller.Controller): def download_invoice(self, id, token): id = int(id) - md5_by_id = request.env['rest.api'].md5_salt(id, 'account.move') - if not md5_by_id == token: + md5_valid = request.env['rest.api'].md5_salt_valid(id, 'account.move', token) + if not md5_valid: return self.response('Unauthorized') pdf, type = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'account.report_invoice')])._render_qweb_pdf([id]) @@ -30,8 +30,8 @@ class Download(controller.Controller): def download_tax_invoice(self, id, token): id = int(id) - md5_by_id = request.env['rest.api'].md5_salt(id, 'account.move') - if not md5_by_id == token: + md5_valid = request.env['rest.api'].md5_salt_valid(id, 'account.move', token) + if not md5_valid: return self.response('Unauthorized') attachment = self._get_attachment('account.move', 'efaktur_document', id) diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 52ccf9fa..9a4b23d9 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -105,6 +105,62 @@ class SaleOrder(controller.Controller): return self.response(data) + @http.route(PREFIX_PARTNER + 'sale_order//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//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/models/account_move.py b/indoteknik_api/models/account_move.py index 3c8fd655..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): diff --git a/indoteknik_api/models/rest_api.py b/indoteknik_api/models/rest_api.py index 052800b7..0a15aad1 100644 --- a/indoteknik_api/models/rest_api.py +++ b/indoteknik_api/models/rest_api.py @@ -14,4 +14,7 @@ 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 \ No newline at end of file diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index c7d488be..cc2f9586 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -32,6 +32,7 @@ class SaleOrder(models.Model): if context == 'with_detail': res_users = self.env['res.users'] data_with_detail = { + 'purchase_order_file': True if sale_order.partner_purchase_order_file else False, 'payment_term': sale_order.payment_term_id.name or '', 'date_order': self.env['rest.api'].datetime_to_str(sale_order.date_order, '%d/%m/%Y %H:%M:%S'), 'products': [], -- cgit v1.2.3 From ef2f9fefe4df844f5a676d2a166dcd4dfdaa249b Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Mon, 6 Feb 2023 16:14:43 +0700 Subject: fix feature --- indoteknik_api/controllers/api_v1/download.py | 28 +++++++++++------ indoteknik_api/controllers/api_v1/sale_order.py | 40 +++++++++++++++++++++++++ indoteknik_api/models/rest_api.py | 29 +++++++++++++++++- indoteknik_api/models/sale_order.py | 3 +- 4 files changed, 89 insertions(+), 11 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/download.py b/indoteknik_api/controllers/api_v1/download.py index f12be337..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,30 +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//', auth='none', method=['GET']) def download_invoice(self, id, token): id = int(id) - md5_valid = request.env['rest.api'].md5_salt_valid(id, 'account.move', token) + 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 request.make_response(pdf, [('Content-Type', 'application/pdf')]) + return rest_api.response_attachment({ + 'content': pdf, + 'mimetype': 'application/pdf', + 'filename': account_move[0]['name'] + }) @http.route(PREFIX + 'download/tax-invoice//', auth='none', method=['GET']) def download_tax_invoice(self, id, token): id = int(id) - md5_valid = request.env['rest.api'].md5_salt_valid(id, 'account.move', token) + 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: - attachment = attachment[0] - return request.make_response(base64.b64decode(attachment['datas']), [('Content-Type', attachment['mimetype'])]) + 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 9a4b23d9..1c67d6c5 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//' @@ -134,6 +135,45 @@ class SaleOrder(controller.Controller): data = sale_order.id return self.response(data) + @http.route(PREFIX_PARTNER + 'sale_order//download_po/', 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//download/', 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//cancel', auth='public', method=['POST', 'OPTIONS'], csrf=False) def partner_cancel_sale_order(self, **kw): user_token = self.authenticate() diff --git a/indoteknik_api/models/rest_api.py b/indoteknik_api/models/rest_api.py index 0a15aad1..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): @@ -17,4 +19,29 @@ class RestApi(models.TransientModel): 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 \ No newline at end of file + 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 cc2f9586..c3f3dccb 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', } @@ -32,7 +34,6 @@ class SaleOrder(models.Model): if context == 'with_detail': res_users = self.env['res.users'] data_with_detail = { - 'purchase_order_file': True if sale_order.partner_purchase_order_file else False, 'payment_term': sale_order.payment_term_id.name or '', 'date_order': self.env['rest.api'].datetime_to_str(sale_order.date_order, '%d/%m/%Y %H:%M:%S'), 'products': [], -- cgit v1.2.3 From 7af09e5b533f76ea12c8b68185c3b904f2aecec9 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 09:17:44 +0700 Subject: add ip_address in user.activity.log --- indoteknik_custom/models/user_activity_log.py | 1 + indoteknik_custom/views/user_activity_log.xml | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index 32b389a1..1a1a84fa 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -11,6 +11,7 @@ class UserActivityLog(models.Model): page_title = fields.Char(string="Judul Halaman") url = fields.Char(string="URL") + ip_address = fields.Char('IP Address') res_user_id = fields.Many2one("res.users", string="User") email = fields.Char(string="Email") update_product = fields.Boolean(string="Update Product") diff --git a/indoteknik_custom/views/user_activity_log.xml b/indoteknik_custom/views/user_activity_log.xml index db242505..70a8f0dd 100755 --- a/indoteknik_custom/views/user_activity_log.xml +++ b/indoteknik_custom/views/user_activity_log.xml @@ -9,6 +9,7 @@ + @@ -22,11 +23,12 @@ - - - - - + + + + + + -- cgit v1.2.3 From 6a306691dd4f5c3ea74c1979802217d5f7091247 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 10:07:27 +0700 Subject: add ip address lookup in user activity log --- indoteknik_custom/models/user_activity_log.py | 13 +++++++++++++ indoteknik_custom/views/user_activity_log.xml | 15 ++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index 1a1a84fa..90d18068 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -1,6 +1,8 @@ from odoo import models, fields from datetime import datetime, timedelta import logging, re +import requests +import json _logger = logging.getLogger(__name__) @@ -12,11 +14,22 @@ 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', compute="_compute_ip_address_lookup") 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 _compute_ip_address_lookup(self): + for log in self: + if log.ip_address: + try: + ipinfo = requests.get('https://ipinfo.io/%s/json' % log.ip_address).json() + del ipinfo['readme'] + log.ip_address_lookup = json.dumps(ipinfo, indent=4, sort_keys=True) + except: + log.ip_address_lookup = '' + def compile_product(self): logs = self.env['user.activity.log'].search([ ('email', '!=', False), diff --git a/indoteknik_custom/views/user_activity_log.xml b/indoteknik_custom/views/user_activity_log.xml index 70a8f0dd..f3112e27 100755 --- a/indoteknik_custom/views/user_activity_log.xml +++ b/indoteknik_custom/views/user_activity_log.xml @@ -19,16 +19,17 @@ user.activity.log.form user.activity.log -
+ - - - - - - + + + + + + + -- cgit v1.2.3 From f5f6c879b46f19361e43d921a319353144233085 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 10:13:58 +0700 Subject: store ip address lookup in user activity log --- indoteknik_custom/models/user_activity_log.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index 90d18068..a7c13993 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -14,7 +14,7 @@ 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', compute="_compute_ip_address_lookup") + ip_address_lookup = fields.Text('IP Address Lookup', compute="_compute_ip_address_lookup", store=True) res_user_id = fields.Many2one("res.users", string="User") email = fields.Char(string="Email") update_product = fields.Boolean(string="Update Product") @@ -22,7 +22,7 @@ class UserActivityLog(models.Model): def _compute_ip_address_lookup(self): for log in self: - if log.ip_address: + if log.ip_address and not log.ip_address_lookup: try: ipinfo = requests.get('https://ipinfo.io/%s/json' % log.ip_address).json() del ipinfo['readme'] -- cgit v1.2.3 From 59b5cbc1cab6a736de031cf6232294b19629342e Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 10:22:06 +0700 Subject: fix compute if ip_address_lookup store=true --- indoteknik_custom/models/user_activity_log.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index a7c13993..478ba119 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -1,4 +1,4 @@ -from odoo import models, fields +from odoo import models, fields, api from datetime import datetime, timedelta import logging, re import requests @@ -20,6 +20,7 @@ class UserActivityLog(models.Model): update_product = fields.Boolean(string="Update Product") product_id = fields.Many2one('product.template', string='Product') + @api.depends('ip_address') def _compute_ip_address_lookup(self): for log in self: if log.ip_address and not log.ip_address_lookup: -- cgit v1.2.3 From effec70a2069499a7289d942759db06af113fc9a Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 10:25:13 +0700 Subject: disable create and edit in user activity log --- indoteknik_custom/views/user_activity_log.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/views/user_activity_log.xml b/indoteknik_custom/views/user_activity_log.xml index f3112e27..9964620a 100755 --- a/indoteknik_custom/views/user_activity_log.xml +++ b/indoteknik_custom/views/user_activity_log.xml @@ -4,7 +4,7 @@ user.activity.log.tree user.activity.log - + @@ -19,7 +19,7 @@ user.activity.log.form user.activity.log - + -- cgit v1.2.3 From 5408b3a7214704742f350b483f48c34e1c84a525 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 10:28:45 +0700 Subject: remove store=true in user activity log --- indoteknik_custom/models/user_activity_log.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index 478ba119..1bb067ab 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -14,13 +14,12 @@ 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', compute="_compute_ip_address_lookup", store=True) + ip_address_lookup = fields.Text('IP Address Lookup', compute="_compute_ip_address_lookup") 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') - @api.depends('ip_address') def _compute_ip_address_lookup(self): for log in self: if log.ip_address and not log.ip_address_lookup: -- cgit v1.2.3 From e62b025b68dcba1b079d6e028458d99116f66946 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 13:55:39 +0700 Subject: ip lookup and record request --- .../controller.cpython-38.pyc.3117987094576 | 0 indoteknik_api/controllers/controller.py | 1 + indoteknik_custom/models/user_activity_log.py | 36 ++++++++++++++++------ indoteknik_custom/views/user_activity_log.xml | 12 +++++--- 4 files changed, 35 insertions(+), 14 deletions(-) create mode 100644 indoteknik_api/controllers/__pycache__/controller.cpython-38.pyc.3117987094576 diff --git a/indoteknik_api/controllers/__pycache__/controller.cpython-38.pyc.3117987094576 b/indoteknik_api/controllers/__pycache__/controller.cpython-38.pyc.3117987094576 new file mode 100644 index 00000000..e69de29b diff --git a/indoteknik_api/controllers/controller.py b/indoteknik_api/controllers/controller.py index c90d3ff1..ffa4e24b 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, diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index 1bb067ab..ad226b74 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -1,4 +1,5 @@ from odoo import models, fields, api +from odoo.http import request from datetime import datetime, timedelta import logging, re import requests @@ -14,21 +15,36 @@ 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', compute="_compute_ip_address_lookup") + ip_address_lookup = fields.Text('IP Address Lookup') 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 _compute_ip_address_lookup(self): - for log in self: - if log.ip_address and not log.ip_address_lookup: - try: - ipinfo = requests.get('https://ipinfo.io/%s/json' % log.ip_address).json() - del ipinfo['readme'] - log.ip_address_lookup = json.dumps(ipinfo, indent=4, sort_keys=True) - except: - log.ip_address_lookup = '' + def _load_ip_address_lookup(self): + domain = [ + ('ip_address', '!=', False), + ('ip_address_lookup', '=', False), + ] + logs = self.search(domain, limit=45, order='create_date asc') + for log in logs: + try: + ipinfo = requests.get('http://ip-api.com/json/%s' % log.ip_address).json() + log.ip_address_lookup = json.dumps(ipinfo, indent=4, sort_keys=True) + except: + log.ip_address_lookup = '' + + def record_activity(self): + try: + httprequest = request.httprequest + 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([ diff --git a/indoteknik_custom/views/user_activity_log.xml b/indoteknik_custom/views/user_activity_log.xml index 9964620a..b0082c3b 100755 --- a/indoteknik_custom/views/user_activity_log.xml +++ b/indoteknik_custom/views/user_activity_log.xml @@ -4,12 +4,12 @@ user.activity.log.tree user.activity.log - + + - @@ -27,11 +27,15 @@ - - + + + + + + -- cgit v1.2.3 From 90442b65e48d6a1e09c7bd23c17f478ce25ba0ca Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 13:56:32 +0700 Subject: delete pycache --- .../controllers/__pycache__/controller.cpython-38.pyc.3117987094576 | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 indoteknik_api/controllers/__pycache__/controller.cpython-38.pyc.3117987094576 diff --git a/indoteknik_api/controllers/__pycache__/controller.cpython-38.pyc.3117987094576 b/indoteknik_api/controllers/__pycache__/controller.cpython-38.pyc.3117987094576 deleted file mode 100644 index e69de29b..00000000 -- cgit v1.2.3 From 241490ce2cc5b9863ec91f127a8e0ee02ca7c2d6 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 14:07:49 +0700 Subject: increase limit load ip address lookup --- indoteknik_custom/models/user_activity_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index ad226b74..b77be8e9 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -26,7 +26,7 @@ class UserActivityLog(models.Model): ('ip_address', '!=', False), ('ip_address_lookup', '=', False), ] - logs = self.search(domain, limit=45, order='create_date asc') + 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() -- cgit v1.2.3 From be72c0e40c034a4cdc90976ecf081715481fd636 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 14:11:40 +0700 Subject: decrease limit load ip address lookup --- indoteknik_custom/models/user_activity_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index b77be8e9..7a19edc3 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -26,7 +26,7 @@ class UserActivityLog(models.Model): ('ip_address', '!=', False), ('ip_address_lookup', '=', False), ] - logs = self.search(domain, limit=100, order='create_date asc') + logs = self.search(domain, limit=50, order='create_date asc') for log in logs: try: ipinfo = requests.get('http://ip-api.com/json/%s' % log.ip_address).json() -- cgit v1.2.3 From c346206759c34502362e1c5412ad70408eb51085 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 14:14:02 +0700 Subject: increase limit load ip address lookup --- indoteknik_custom/models/user_activity_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index 7a19edc3..b77be8e9 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -26,7 +26,7 @@ class UserActivityLog(models.Model): ('ip_address', '!=', False), ('ip_address_lookup', '=', False), ] - logs = self.search(domain, limit=50, order='create_date asc') + 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() -- cgit v1.2.3 From 2339c6c6a38fdbb8cee512ae61131d01a1a9c917 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 14:17:16 +0700 Subject: delete ip lookup status --- indoteknik_custom/models/user_activity_log.py | 1 + 1 file changed, 1 insertion(+) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index b77be8e9..699c9f3b 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -30,6 +30,7 @@ class UserActivityLog(models.Model): 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 = '' -- cgit v1.2.3 From d2fcc3208afcab10502955f2e6554383ff376135 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 14:29:01 +0700 Subject: listen request on image --- indoteknik_api/controllers/controller.py | 1 + 1 file changed, 1 insertion(+) diff --git a/indoteknik_api/controllers/controller.py b/indoteknik_api/controllers/controller.py index ffa4e24b..59885148 100644 --- a/indoteknik_api/controllers/controller.py +++ b/indoteknik_api/controllers/controller.py @@ -150,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')]) -- cgit v1.2.3 From ce2f02d9c7b739490787fed76e5a7a6a55f44066 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 14:37:16 +0700 Subject: fix dont add record if from localhost ip --- indoteknik_custom/models/user_activity_log.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index 699c9f3b..743abf60 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -38,10 +38,11 @@ class UserActivityLog(models.Model): def record_activity(self): try: httprequest = request.httprequest + ip_address = httprequest.remote_addr if httprequest.remote_addr != '127.0.0.1' else '' 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 + 'ip_address': ip_address }]) return True except: -- cgit v1.2.3 From 0388c78c3bbe0f5a6325fee7bb7b2e6a7d436a5f Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 14:39:34 +0700 Subject: fix dont add record if from localhost ip --- indoteknik_custom/models/user_activity_log.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index 743abf60..879d5402 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -38,12 +38,12 @@ class UserActivityLog(models.Model): def record_activity(self): try: httprequest = request.httprequest - ip_address = httprequest.remote_addr if httprequest.remote_addr != '127.0.0.1' else '' - 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': ip_address - }]) + 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 -- cgit v1.2.3 From 7478616937cff56ccb994138831f90eae904e724 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 16:54:09 +0700 Subject: user activity log detail --- indoteknik_custom/models/user_activity_log.py | 34 +++++++++++++++++++++++++++ indoteknik_custom/views/user_activity_log.xml | 10 ++++++++ 2 files changed, 44 insertions(+) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index 879d5402..9d9694af 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -16,11 +16,44 @@ class UserActivityLog(models.Model): 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&hl=id&z=15&output=embed' % (ip_location_lat, ip_location_lon) + if ip_location_lat and ip_location_lon: + self.ip_location_map = "" + + 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), @@ -34,6 +67,7 @@ class UserActivityLog(models.Model): 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: diff --git a/indoteknik_custom/views/user_activity_log.xml b/indoteknik_custom/views/user_activity_log.xml index b0082c3b..b8792ee8 100755 --- a/indoteknik_custom/views/user_activity_log.xml +++ b/indoteknik_custom/views/user_activity_log.xml @@ -32,9 +32,19 @@ + + + + + + + + + + -- cgit v1.2.3 From 5bdb2c10b3955d7bec4aa4b88d16bdf34f2f825a Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Tue, 7 Feb 2023 16:55:40 +0700 Subject: user activity log detail --- indoteknik_custom/views/user_activity_log.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/indoteknik_custom/views/user_activity_log.xml b/indoteknik_custom/views/user_activity_log.xml index b8792ee8..91c14b4d 100755 --- a/indoteknik_custom/views/user_activity_log.xml +++ b/indoteknik_custom/views/user_activity_log.xml @@ -8,6 +8,7 @@ + -- cgit v1.2.3 From 2418642c82c8cdb531c3a1e80b8ec7b990d05300 Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Thu, 9 Feb 2023 08:26:08 +0700 Subject: fix due date after dunning run --- indoteknik_custom/models/dunning_run.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/indoteknik_custom/models/dunning_run.py b/indoteknik_custom/models/dunning_run.py index ed5d7bb5..ee0669ca 100644 --- a/indoteknik_custom/models/dunning_run.py +++ b/indoteknik_custom/models/dunning_run.py @@ -1,5 +1,6 @@ from odoo import models, api, fields from odoo.exceptions import AccessError, UserError, ValidationError +from datetime import timedelta import logging _logger = logging.getLogger(__name__) @@ -30,10 +31,24 @@ class DunningRun(models.Model): invoice = line.invoice_id if not invoice.date_kirim_tukar_faktur: invoice.date_kirim_tukar_faktur = self.date_kirim_tukar_faktur + tukar_date = self.date_kirim_tukar_faktur + term = invoice.invoice_payment_term_id + add_days = 0 + for line in term.line_ids: + add_days += line.days + due_date = tukar_date + timedelta(days=add_days) + invoice.invoice_date_due = due_date if not invoice.resi_tukar_faktur: invoice.resi_tukar_faktur = self.resi_tukar_faktur if not invoice.date_terima_tukar_faktur: invoice.date_terima_tukar_faktur = self.date_terima_tukar_faktur + tukar_date = self.date_terima_tukar_faktur + term = invoice.invoice_payment_term_id + add_days = 0 + for line in term.line_ids: + add_days += line.days + due_date = tukar_date + timedelta(days=add_days) + invoice.invoice_date_due = due_date if not invoice.shipper_faktur_id: invoice.shipper_faktur_id = self.shipper_faktur_id -- cgit v1.2.3 From 3f5f262fb49f3d30f98de8e5fdfe6e6e15e904da Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Thu, 9 Feb 2023 11:03:19 +0700 Subject: comment unecessary code --- indoteknik_custom/models/account_move.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 54e51dcf..78fa2ddf 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -21,8 +21,8 @@ class AccountMove(models.Model): def action_post(self): res = super(AccountMove, self).action_post() - if not self.env.user.is_accounting: - raise UserError('Hanya Accounting yang bisa Posting') + # if not self.env.user.is_accounting: + # raise UserError('Hanya Accounting yang bisa Posting') return res @api.onchange('date_kirim_tukar_faktur') -- cgit v1.2.3 From 6db1ecd687f0e09ba448fbee3b0d9a397b307567 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Thu, 9 Feb 2023 16:25:29 +0700 Subject: change limit ip address lookup --- indoteknik_custom/models/user_activity_log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/models/user_activity_log.py b/indoteknik_custom/models/user_activity_log.py index 9d9694af..ef801ca5 100755 --- a/indoteknik_custom/models/user_activity_log.py +++ b/indoteknik_custom/models/user_activity_log.py @@ -59,7 +59,7 @@ class UserActivityLog(models.Model): ('ip_address', '!=', False), ('ip_address_lookup', '=', False), ] - logs = self.search(domain, limit=100, order='create_date asc') + logs = self.search(domain, limit=45, order='create_date asc') for log in logs: try: ipinfo = requests.get('http://ip-api.com/json/%s' % log.ip_address).json() -- cgit v1.2.3 From b0de64ae769148a009d0a08a957c5c35dee174a9 Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Fri, 10 Feb 2023 10:35:55 +0700 Subject: add notification in dunning run --- indoteknik_custom/models/dunning_run.py | 3 +++ indoteknik_custom/views/dunning_run.xml | 1 + 2 files changed, 4 insertions(+) diff --git a/indoteknik_custom/models/dunning_run.py b/indoteknik_custom/models/dunning_run.py index ee0669ca..98689550 100644 --- a/indoteknik_custom/models/dunning_run.py +++ b/indoteknik_custom/models/dunning_run.py @@ -23,6 +23,7 @@ class DunningRun(models.Model): date_terima_tukar_faktur = fields.Date(string='Terima Faktur') shipper_faktur_id = fields.Many2one('delivery.carrier', string='Shipper Faktur') is_validated = fields.Boolean(string='Validated') + notification = fields.Char(string='Notification') def copy_date_faktur(self): if not self.is_validated: @@ -51,12 +52,14 @@ class DunningRun(models.Model): invoice.invoice_date_due = due_date if not invoice.shipper_faktur_id: invoice.shipper_faktur_id = self.shipper_faktur_id + self.notification = 'Berhasil copy tanggal terima faktur ke setiap invoice %s' % self.date_terima_tukar_faktur def validate_dunning(self): if not self.dunning_line: raise UserError('Dunning Line masih kosong, generate dulu') else: self.is_validated = True + self.notification = 'Jangan lupa klik Copy Date jika sudah ada tanggal kirim / tanggal terima faktur' def generate_dunning_line(self): if self.is_validated: diff --git a/indoteknik_custom/views/dunning_run.xml b/indoteknik_custom/views/dunning_run.xml index 6343a79b..cae9cc32 100644 --- a/indoteknik_custom/views/dunning_run.xml +++ b/indoteknik_custom/views/dunning_run.xml @@ -63,6 +63,7 @@ + -- cgit v1.2.3