summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzka Nathan <darizkyfaz@gmail.com>2026-01-01 06:13:19 +0700
committerAzka Nathan <darizkyfaz@gmail.com>2026-01-01 06:13:19 +0700
commit956be5a7ac4cd008dad9c854f1ba2e5b1346cc01 (patch)
tree58de506497a0562748487ada2d9c9906906836a7
parent1f3660c422500d06676547e10292536b7a6a5f8b (diff)
parent4f29a01888d72ffe07ebffa4e9e0637efb2495d2 (diff)
Merge branch 'main' of bitbucket.org:altafixco/fixco-addons
# Conflicts: # fixco_custom/models/webhook_ginee.py
-rw-r--r--fixco_custom/models/account_move.py13
-rwxr-xr-xfixco_custom/models/detail_order.py92
-rwxr-xr-xfixco_custom/models/webhook_ginee.py25
3 files changed, 70 insertions, 60 deletions
diff --git a/fixco_custom/models/account_move.py b/fixco_custom/models/account_move.py
index 63b3e8e..58c94f7 100644
--- a/fixco_custom/models/account_move.py
+++ b/fixco_custom/models/account_move.py
@@ -1,3 +1,4 @@
+from cmath import e
from odoo import models, api, fields, _
from odoo.exceptions import AccessError, UserError, ValidationError
from datetime import timedelta, date, datetime
@@ -63,7 +64,7 @@ class AccountMove(models.Model):
def export_faktur_to_xml(self):
valid_invoices = self
-
+
coretax_faktur = self.env['coretax.faktur'].create({})
response = coretax_faktur.export_to_download(
@@ -130,7 +131,7 @@ class AccountMove(models.Model):
'target': 'current',
'domain': [('id', 'in', list(reverses.ids))],
}
-
+
def action_reverse(self):
action = self.env["ir.actions.actions"]._for_xml_id("account.action_view_account_move_reversal")
@@ -198,10 +199,12 @@ class AccountMove(models.Model):
res = super(AccountMove, self).action_post()
for entry in self:
if entry.move_type == 'out_invoice':
- entry.invoice_date = entry.picking_id.date_done
+ if entry.picking_id:
+ entry.invoice_date = entry.picking_id.date_done
+
return res
-
+
@api.onchange('purchase_vendor_bill_ids', 'purchase_id')
def _onchange_purchase_auto_complete(self):
""" Load from either multiple old purchase orders or vendor bills. """
@@ -235,7 +238,7 @@ class AccountMove(models.Model):
new_lines += new_line
new_lines._onchange_mark_recompute_taxes()
-
+
# Compute invoice_origin
origins = set(self.line_ids.mapped('purchase_line_id.order_id.name'))
diff --git a/fixco_custom/models/detail_order.py b/fixco_custom/models/detail_order.py
index 3e2a6d8..41a5466 100755
--- a/fixco_custom/models/detail_order.py
+++ b/fixco_custom/models/detail_order.py
@@ -48,20 +48,26 @@ class DetailOrder(models.Model):
def get_order_id(self):
try:
- if self.json_ginee:
+ if self.json_ginee:
json_data = json.loads(self.json_ginee)
order_id = json_data.get('payload', {}).get('orderId')
if not order_id:
raise UserError(_("Order ID not found in JSON data"))
- return order_id
+ return order_id
raise UserError(_("No JSON data available"))
except json.JSONDecodeError:
raise UserError(_("Invalid JSON format in json_ginee field"))
except Exception as e:
raise UserError(_("Error extracting order ID: %s") % str(e))
+ # def process_queue_item(self, limit=100):
+ # domain = [('create_date', '>', '2025-12-31 23:59:59')]
+ # records = self.search(domain, order='create_date asc', limit=limit)
+ # for rec in records:
+ # rec.execute_queue()
+
def process_queue_item(self, limit=100):
- domain = [('create_date', '>', '2025-12-31 23:59:59')]
+ domain = [('execute_status', '=', False)]
records = self.search(domain, order='create_date asc', limit=limit)
for rec in records:
rec.execute_queue()
@@ -70,28 +76,28 @@ class DetailOrder(models.Model):
def execute_queue(self):
try:
order_id = self.get_order_id()
-
+
authorization = self.sign_request()
headers = {
'Content-Type': 'application/json',
'X-Advai-Country': 'ID',
'Authorization': authorization
}
-
+
payload = {
"orderIds": [order_id]
}
-
+
# URL endpoint Ginee
url = "https://api.ginee.com/openapi/order/v1/batch-get"
-
+
# Melakukan POST request
response = requests.post(
url,
headers=headers,
data=json.dumps(payload)
)
-
+
# Cek status response
if response.status_code == 200:
data = response.json()
@@ -104,7 +110,7 @@ class DetailOrder(models.Model):
'response': response.text
})
})
-
+
except Exception as e:
self.write({
'message_error': json.dumps({
@@ -118,7 +124,7 @@ class DetailOrder(models.Model):
def get_order_id_detail(self):
try:
- if self.detail_order:
+ if self.detail_order:
json_data = json.loads(self.detail_order)
order_id = json_data.get('data', {})[0].get('orderId')
order_status = json_data.get('data', {})[0].get('orderStatus')
@@ -131,7 +137,7 @@ class DetailOrder(models.Model):
raise UserError(_("Invalid JSON format in detail_order field"))
except Exception as e:
raise UserError(_("Error extracting order ID: %s") % str(e))
-
+
def process_queue_item_detail(self, limit=100):
domain = [
('execute_status', '=', 'detail_order'),
@@ -142,7 +148,7 @@ class DetailOrder(models.Model):
]
records = self.search(domain, order='create_date desc', limit=limit)
-
+
for i, rec in enumerate(records, 1):
try:
rec.execute_queue_detail()
@@ -151,9 +157,9 @@ class DetailOrder(models.Model):
except Exception as e:
_logger.error("Failed to process record %s: %s", rec.id, str(e))
self.env.cr.rollback()
-
+
self.env.cr.commit()
-
+
def get_partner(self, shop_id):
partner = self.env['res.partner'].search([('ginee_shop_id', '=', shop_id)], limit=1)
if not partner:
@@ -172,7 +178,7 @@ class DetailOrder(models.Model):
'channel': json_data.get('data', {})[0].get('channel'),
}
return data
-
+
def _combine_order_items(self, items):
"""Combine quantities of the same products from multiple orders"""
product_quantities = {}
@@ -190,25 +196,25 @@ class DetailOrder(models.Model):
'item_data': item # Keep original item data
}
return product_quantities
-
+
def prepare_data_so_line(self, json_data):
order_lines = []
product_not_found = False
-
+
# Get all items (already combined if grouped)
items = json_data.get('data', [{}])[0].get('items', [])
-
+
# Combine quantities of the same products
product_quantities = self._combine_order_items(items)
-
+
# Process the combined items
for sku, combined_item in product_quantities.items():
item = combined_item['item_data']
product = self.env['product.product'].search(
- [('default_code', '=', sku)],
+ [('default_code', '=', sku)],
limit=1
)
-
+
if product and item.get('masterSkuType') == 'BUNDLE':
order_lines.append((0, 0, {
'display_type': 'line_note',
@@ -216,18 +222,18 @@ class DetailOrder(models.Model):
'product_uom_qty': 0,
'price_unit': 0,
}))
-
+
bundling_lines = self.env['bundling.line'].search([('product_id', '=', product.id)])
bundling_variant_ids = bundling_lines.mapped('variant_id').ids
sale_pricelist = self.env['product.pricelist.item'].search([
- ('product_id', 'in', bundling_variant_ids),
+ ('product_id', 'in', bundling_variant_ids),
('pricelist_id', '=', 17)
])
price_bundling_bottom = sum(item.fixed_price for item in sale_pricelist)
-
+
for bline in bundling_lines:
bottom_price = self.env['product.pricelist.item'].search([
- ('product_id', '=', bline.variant_id.id),
+ ('product_id', '=', bline.variant_id.id),
('pricelist_id', '=', 17)
], limit=1)
price = bottom_price.fixed_price
@@ -251,43 +257,43 @@ class DetailOrder(models.Model):
'price_unit': 0,
}))
continue
-
+
# Regular product line
line_data = {
'product_id': product.id if product else 5792,
'product_uom_qty': combined_item['quantity'],
'price_unit': combined_item['actualPrice'],
}
-
+
if not product:
line_data['name'] = f"{sku} ({combined_item['productName']})"
product_not_found = True
-
+
order_lines.append((0, 0, line_data))
-
+
return order_lines, product_not_found
- def execute_queue_detail(self):
+ def execute_queue_detail(self):
try:
json_data = json.loads(self.detail_order)
data = self.prepare_data_so(json_data)
order_lines, product_not_found = self.prepare_data_so_line(json_data)
order_id, order_status, print_info = self.get_order_id_detail()
-
+
# First check if a sale order with this reference already exists
existing_order = self.env['sale.order'].search([('order_reference', '=', order_id)], limit=1)
-
+
if order_status == 'CANCELLED':
external_order_id = json_data.get('data', [{}])[0].get('externalOrderId')
order_id = json_data.get('data', [{}])[0].get('orderId')
-
+
# Try to find existing SO
existing_order = self.env['sale.order'].search([
'|',
('invoice_mp', '=', external_order_id),
('client_order_ref', '=', order_id)
], limit=1)
-
+
if existing_order:
if existing_order.state == 'sale':
# Cancel all pickings linked to this order
@@ -301,22 +307,22 @@ class DetailOrder(models.Model):
existing_order.action_cancel()
self.sale_id = existing_order.id
self.execute_status = 'cancelled_so'
-
+
else:
# If no existing SO, create one, then cancel
data = self.prepare_data_so(json_data)
order_lines, product_not_found = self.prepare_data_so_line(json_data)
data['order_line'] = order_lines
sale_order = self.env['sale.order'].create(data)
-
+
self.sale_id = sale_order.id
sale_order.order_reference = order_id
sale_order.address = json_data.get('data', [{}])[0].get('shippingAddressInfo', []).get('fullAddress', [])
sale_order.note_by_buyer = json_data.get('data', [{}])[0].get('extraInfo', []).get('noteByBuyer', [])
-
+
sale_order.action_cancel()
self.execute_status = 'cancelled_so_created'
-
+
return
if existing_order:
@@ -325,11 +331,11 @@ class DetailOrder(models.Model):
self.execute_status = 'already_so'
return # Exit early since we don't need to create anything
- if order_status != 'PENDING_PAYMENT':
+ if order_status != 'PENDING_PAYMENT':
if order_status in ('PARTIALLY_PAID', 'PAID'):
data['order_line'] = order_lines
sale_order = self.env['sale.order'].create(data)
-
+
self.sale_id = sale_order.id
sale_order.order_reference = order_id
sale_order.address = json_data.get('data', [{}])[0].get('shippingAddressInfo', []).get('fullAddress', [])
@@ -350,7 +356,7 @@ class DetailOrder(models.Model):
# For other statuses, create new order only if it doesn't exist
data['order_line'] = order_lines
sale_order = self.env['sale.order'].create(data)
-
+
self.sale_id = sale_order.id
sale_order.order_reference = order_id
sale_order.address = json_data.get('data', [{}])[0].get('shippingAddressInfo', []).get('fullAddress', [])
@@ -381,9 +387,9 @@ class DetailOrder(models.Model):
hmac.new(SECRET_KEY.encode('utf-8'), signData.encode('utf-8'), digestmod=sha256).digest()
).decode('ascii')
return authorization
-
+
def prorate_price_bundling(self, product, sum_bottom, price_bottom,actual_price):
percent = price_bottom / sum_bottom
real_price = percent * actual_price
- return real_price \ No newline at end of file
+ return real_price
diff --git a/fixco_custom/models/webhook_ginee.py b/fixco_custom/models/webhook_ginee.py
index 606bd21..444306b 100755
--- a/fixco_custom/models/webhook_ginee.py
+++ b/fixco_custom/models/webhook_ginee.py
@@ -19,23 +19,24 @@ class WebhookGinee(models.Model):
('not_found', 'Record not found')
], 'Execute Status')
- # def process_queue_item(self, limit=100, max_exec_time=30):
- # domain = [('execute_status', '=', False)]
- # records = self.search(domain, order='create_date asc', limit=limit)
- # start_time = time.time()
- # for rec in records:
- # end_time = time.time()
- # elapsed_time = end_time - start_time
- # if elapsed_time > max_exec_time:
- # break
- # rec.execute_queue()
-
- def process_queue_item(self, limit=100):
+ def process_queue_item(self, limit=100, max_exec_time=30):
domain = [('execute_status', '=', False)]
records = self.search(domain, order='create_date asc', limit=limit)
+ start_time = time.time()
for rec in records:
+ end_time = time.time()
+ elapsed_time = end_time - start_time
+ if elapsed_time > max_exec_time:
+ break
rec.execute_queue()
+ # def process_queue_item(self, limit=100):
+ # domain = [('create_date', '>', '2025-12-31 23:59:59')]
+ # records = self.search(domain, order='create_date asc', limit=limit)
+ # for rec in records:
+ # rec.execute_queue()
+
+
def execute_queue(self):
detail_order = self.env['detail.order'].create({
'json_ginee': self.json_ginee,