diff options
| author | Azka Nathan <darizkyfaz@gmail.com> | 2025-06-23 15:22:18 +0700 |
|---|---|---|
| committer | Azka Nathan <darizkyfaz@gmail.com> | 2025-06-23 15:22:18 +0700 |
| commit | 8e8da88ec748a1a46b1d9d4bf1d24be2ca14655a (patch) | |
| tree | 7336c659f2ebfdbb606574a304e5dd166457a231 | |
| parent | 7d22bf1355720a8f571476738e0f06f580b2546c (diff) | |
upload manual ginee
| -rwxr-xr-x | fixco_custom/__manifest__.py | 1 | ||||
| -rwxr-xr-x | fixco_custom/models/__init__.py | 1 | ||||
| -rw-r--r-- | fixco_custom/models/upload_ginee.py | 175 | ||||
| -rwxr-xr-x | fixco_custom/security/ir.model.access.csv | 4 | ||||
| -rwxr-xr-x | fixco_custom/views/detail_order.xml | 2 | ||||
| -rw-r--r-- | fixco_custom/views/ir_sequence.xml | 11 | ||||
| -rw-r--r-- | fixco_custom/views/upload_ginee.xml | 63 |
7 files changed, 256 insertions, 1 deletions
diff --git a/fixco_custom/__manifest__.py b/fixco_custom/__manifest__.py index 7552daf..20d27c0 100755 --- a/fixco_custom/__manifest__.py +++ b/fixco_custom/__manifest__.py @@ -29,6 +29,7 @@ 'views/print_picking_list.xml', 'views/uangmuka_penjualan.xml', 'views/sale_pricelist.xml', + 'views/upload_ginee.xml', ], 'demo': [], 'css': [], diff --git a/fixco_custom/models/__init__.py b/fixco_custom/models/__init__.py index 5ea3cef..4fd81d8 100755 --- a/fixco_custom/models/__init__.py +++ b/fixco_custom/models/__init__.py @@ -15,3 +15,4 @@ from . import stock_picking_shipment_group from . import print_picking_list from . import stock_picking_print_picking_list from . import uangmuka_penjualan +from . import upload_ginee diff --git a/fixco_custom/models/upload_ginee.py b/fixco_custom/models/upload_ginee.py new file mode 100644 index 0000000..0910ef3 --- /dev/null +++ b/fixco_custom/models/upload_ginee.py @@ -0,0 +1,175 @@ +from odoo import models, fields, api, _ +from datetime import datetime +import base64 +import xlrd +from odoo.exceptions import ValidationError, UserError +import time +import requests +import json +import hmac +from hashlib import sha256 + +Request_URI = '/openapi/order/v1/batch-get' +ACCESS_KEY = '24bb6a1ec618ec6a' +SECRET_KEY = '32e4a78ad05ee230' + +class UploadGinee(models.Model): + _name = "upload.ginee" + _description = "Upload Ginee" + _order = "create_date desc" + _rec = "number" + + ginee_lines = fields.One2many('upload.ginee.line', 'upload_ginee_id', string='Upload Ginee Lines', auto_join=True, copy=False) + number = fields.Char('Number', copy=False) + date_upload = fields.Datetime('Upload Date', copy=False) + user_id = fields.Many2one('res.users', string='Created By', copy=False, default=lambda self: self.env.user.id) + excel_file = fields.Binary('Excel File', attachment=True) + filename = fields.Char('File Name') + filename = fields.Char('File Name') + + @api.model + def create(self, vals): + vals['number'] = self.env['ir.sequence'].next_by_code('upload.ginee') or '/' + return super(UploadGinee, self).create(vals) + + def action_import_excel(self): + self.ensure_one() + if not self.excel_file: + raise ValidationError(_("Please upload an Excel file first.")) + + try: + file_content = base64.b64decode(self.excel_file) + workbook = xlrd.open_workbook(file_contents=file_content) + sheet = workbook.sheet_by_index(0) + except: + raise ValidationError(_("Invalid Excel file format.")) + + header = [str(sheet.cell(0, col).value).strip().lower() for col in range(sheet.ncols)] + expected_headers = ['marketplace', 'shop', 'invoice', 'order id'] + + if not all(h in header for h in expected_headers): + raise ValidationError(_("Invalid Excel format. Expected columns: Marketplace, Shop, Invoice, Order Id")) + + marketplace_col = header.index('marketplace') + shop_col = header.index('shop') + invoice_col = header.index('invoice') + order_id_col = header.index('order id') + + line_vals_list = [] + for row in range(1, sheet.nrows): + try: + marketplace = str(sheet.cell(row, marketplace_col).value).strip() + shop = str(sheet.cell(row, shop_col).value).strip() + invoice_marketplace = str(sheet.cell(row, invoice_col).value).strip() + order_id = str(sheet.cell(row, order_id_col).value).strip() + + line_vals = { + 'marketplace': marketplace, + 'shop': shop, + 'invoice_marketplace': invoice_marketplace, + 'order_id': order_id, + 'upload_ginee_id': self.id, + } + line_vals_list.append((0, 0, line_vals)) + except Exception as e: + continue + + self.ginee_lines.unlink() + self.write({ + 'ginee_lines': line_vals_list, + }) + + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'params': { + 'title': _('Success'), + 'message': _('Imported %s lines from Excel.') % len(line_vals_list), + 'sticky': False, + 'next': {'type': 'ir.actions.act_window_close'}, + } + } + + def action_create_detail_order(self): + for line in self.ginee_lines: + self.date_upload = datetime.utcnow() + line.create_so_and_detail_order() + + + +class UploadGineeLine(models.Model): + _name = "upload.ginee.line" + _description = "Upload Ginee Line" + _inherit = ['mail.thread'] + + upload_ginee_id = fields.Many2one('upload.ginee', string='Upload Ginee') + marketplace = fields.Char('Marketplace') + shop = fields.Char('Shop') + invoice_marketplace = fields.Char('Invoice Marketplace') + order_id = fields.Char('Order ID') + message_error = fields.Text('Message Error') + detail_order_id = fields.Many2one('detail.order', string='Detail Order') + + def create_so_and_detail_order(self): + try: + order_id = f"{self.order_id}" + + duplicate_detail_order = self.env['detail.order'].search([ + ('detail_order','ilike', order_id) + ]) + + if duplicate_detail_order: + raise UserError(f'Untuk SO Dengan Order Id {order_id} sudah ada di detail order') + + authorization = self.sign_request() + headers = { + 'Content-Type': 'application/json', + 'X-Advai-Country': 'ID', + 'Authorization': authorization + } + + payload = { + "orderIds": [order_id] + } + + url = "https://api.ginee.com/openapi/order/v1/batch-get" + + response = requests.post( + url, + headers=headers, + data=json.dumps(payload) + ) + + if response.status_code == 200: + data = response.json() + # self.detail_order = json.dumps(data, indent=4, sort_keys=True) + detail_order = self.env['detail.order'].create([{ + 'detail_order': json.dumps(data, indent=4, sort_keys=True), + 'source': 'manual', + }]) + + detail_order.execute_queue_detail() + self.message_error = 'Success!!' + self.detail_order_id = detail_order.id + else: + self.write({ + 'message_error': json.dumps({ + 'error': f"Request failed with status code {response.status_code}", + 'response': response.text + }) + }) + + except Exception as e: + self.write({ + 'message_error': json.dumps({ + 'error': str(e) + }) + }) + + + def sign_request(self): + signData = '$'.join(['POST', Request_URI]) + '$' + authorization = ACCESS_KEY + ':' + base64.b64encode( + hmac.new(SECRET_KEY.encode('utf-8'), signData.encode('utf-8'), digestmod=sha256).digest() + ).decode('ascii') + return authorization
\ No newline at end of file diff --git a/fixco_custom/security/ir.model.access.csv b/fixco_custom/security/ir.model.access.csv index bc0b1f0..1fa0a59 100755 --- a/fixco_custom/security/ir.model.access.csv +++ b/fixco_custom/security/ir.model.access.csv @@ -19,4 +19,6 @@ access_print_picking_list,access.shipment.group,model_print_picking_list,,1,1,1, access_print_picking_list_line,access.shipment.group.line,model_print_picking_list_line,,1,1,1,1 access_stock_picking_print_picking_list,access.stock.picking.print_picking_list,model_stock_picking_print_picking_list,,1,1,1,1 access_uangmuka_penjualan,access.uangmuka.penjualan,model_uangmuka_penjualan,,1,1,1,1 -access_picking_line,access.picking.line,model_picking_line,,1,1,1,1
\ No newline at end of file +access_picking_line,access.picking.line,model_picking_line,,1,1,1,1 +access_upload_ginee,access.upload.ginee,model_upload_ginee,,1,1,1,1 +access_upload_ginee_line,access.upload.ginee.line,model_upload_ginee_line,,1,1,1,1
\ No newline at end of file diff --git a/fixco_custom/views/detail_order.xml b/fixco_custom/views/detail_order.xml index 5ab2116..beb6d5c 100755 --- a/fixco_custom/views/detail_order.xml +++ b/fixco_custom/views/detail_order.xml @@ -10,6 +10,7 @@ <field name="sale_id"/> <field name="picking_id"/> <field name="invoice_id"/> + <field name="source"/> <field name="execute_status"/> <field name="create_date" optional="hide"/> <field name="write_date" optional="hide"/> @@ -44,6 +45,7 @@ <field name="sale_id"/> <field name="picking_id"/> <field name="invoice_id"/> + <field name="source"/> <field name="message_error"/> <field name="execute_status"/> </group> diff --git a/fixco_custom/views/ir_sequence.xml b/fixco_custom/views/ir_sequence.xml index 395add6..de2188b 100644 --- a/fixco_custom/views/ir_sequence.xml +++ b/fixco_custom/views/ir_sequence.xml @@ -11,6 +11,17 @@ <field name="number_increment">1</field> <field name="company_id">4</field> </record> + + <record id="sequence_upload_ginee" model="ir.sequence"> + <field name="name">Upload Ginee</field> + <field name="code">upload.ginee</field> + <field name="active">TRUE</field> + <field name="prefix">UG/%(year)s/</field> + <field name="padding">5</field> + <field name="number_next">1</field> + <field name="number_increment">1</field> + <field name="company_id">4</field> + </record> <record id="sequence_shipment_group" model="ir.sequence"> <field name="name">Shipment Group</field> diff --git a/fixco_custom/views/upload_ginee.xml b/fixco_custom/views/upload_ginee.xml new file mode 100644 index 0000000..99ecb1e --- /dev/null +++ b/fixco_custom/views/upload_ginee.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<odoo> + <data> + <record id="upload_ginee_tree" model="ir.ui.view"> + <field name="name">upload.ginee.tree</field> + <field name="model">upload.ginee</field> + <field name="arch" type="xml"> + <tree default_order="create_date desc"> + <field name="number"/> + <field name="date_upload"/> + <field name="user_id"/> + </tree> + </field> + </record> + + <record id="view_upload_ginee_form" model="ir.ui.view"> + <field name="name">upload.ginee.form</field> + <field name="model">upload.ginee</field> + <field name="arch" type="xml"> + <form string="Upload Ginee"> + <header> + <button name="action_import_excel" string="Import Excel" type="object" class="oe_highlight"/> + <button name="action_create_detail_order" string="Create Detail Order" type="object" class="oe_highlight"/> + <field name="number" widget="field_no_edit" options="{'no_open': True}"/> + <field name="date_upload"/> + <field name="user_id" widget="field_no_edit" options="{'no_open': True}"/> + </header> + <sheet> + <group> + <field name="excel_file" filename="filename"/> + <field name="filename" invisible="1"/> + </group> + <field name="ginee_lines"> + <tree editable="bottom"> + <field name="marketplace"/> + <field name="shop"/> + <field name="invoice_marketplace"/> + <field name="order_id"/> + <field name="detail_order_id"/> + <field name="message_error"/> + </tree> + </field> + </sheet> + </form> + </field> + </record> + + <record id="upload_ginee_action" model="ir.actions.act_window"> + <field name="name">Upload Ginee</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">upload.ginee</field> + <field name="view_mode">tree,form</field> + </record> + + <menuitem + id="menu_upload_ginee" + name="Upload Ginee" + parent="sale.menu_sale_report" + sequence="4" + action="upload_ginee_action" + /> + </data> +</odoo> |
