Many Empty Records Returned - GetNewGLJrnDtlMnl

Hi

Using the REST API I am calling “GetNewGLJrnDtlMnl” on “Erp.BO.GLJournalEntrySvc”.

I am getting some strange results with over a 100 empty GLJrnHed as part of the result set and not one of them is a the GLJrnHed data I sent to begin with.

How can I delete these?

I’m pretty sure those empty records are from where you made them a couple days ago judging from this thread:

You are probably not doing the process correctly.

I would post your code here or there so we can assist.

I don’t have enough knowledge of the GL to know the correct answer on this, so I’ll let someone else chime in before I help make them go away.

Thanks for response.

The flow is as follows:

  1. Create GL Journal Group
    a. Erp.Bo.GLJrnGrrpSvc - GetNewGLJrnGrp
    b. Erp.Bo.GLJrnGrrpSvc - Update

  2. Create the GL Journal Header
    a. Erp.Bo.GLJournalEntrySvc - GetNewGLJrnHedTran
    b. Erp.Bo.GLJournalEntrySvc - PreUpdate
    c. Erp.Bo.GLJournalEntrySvc - Update

  3. Create the GL Journal Detail - a Manual Journals
    a. Erp.Bo.GLJournalEntrySvc - GetNewGLJrnDtlMnl ( Trace show a call to ChangeGlAcct1() but there is no need here as none of my GL Account will trigger anything)
    b. Erp.Bo.GLJournalEntrySvc - Update

I’m rolling my own classes below (as I don’t need the hundreds properties to create a basic entry).
I’m expecting back from 3a either s GLJrnDtlMnl object (index 0) which will be simply sent back to Update to actually create the records. But I have hundreds of empty records and no idea on how to delete. They aren’t yet saved as database record so I have no SysRowID I can simply delete against.

Below is python code. More to proto-type and diagnose (it aint pretty).
Looking to build into a C# solution as part of an Excel Addin.

I’m dangerous enough to understand how this could works but yet good enough to do this well.
Mostly hardcoded but only to get a single row loaded then will be made more dynamic.

from json import JSONDecodeError
import requests
import urllib.parse 
import os
from base64 import b64encode
from config import logger
import time
import jsons

class Epicor(object):
  companies = ['aaaaa', 'bbbbb, 'ccccc, 'dddddd']

  api_headers = {'X-API-Key' : os.getenv('EPICOR_API'),
           'Authorization' : f'Basic {os.getenv("EPICOR_AUTH")}',
           'accept' : 'application/json',
           'Content-Type' : 'application/json'}
  dev_url = "https://xxxxxxxx.epicorsaas.com/xxxxpilot/api/v2/odata"
  live_url = "https://xxxxxxxx.epicorsaas.com/xxxx201/api/v2/odata"
    
  # Authorization token: we need to base 64 encode it 
  # and then decode it to acsii as python 3 stores it as a byte string
  def basic_auth(self, username, password):
      token = b64encode(f"{username}:{password}".encode('utf-8')).decode("ascii")
      return f'Basic {token}'
  
  def __init__(self, live=False, company=None, username=None, password=None):
    self.base_url = Epicor.live_url if live else Epicor.dev_url
    self.service_url = None
    self.servce = None
    self.company = company
    auth = self.basic_auth(os.getenv("EPICOR_USER"), os.getenv("EPICOR_PASS"))
    self.api_headers['Authorization'] = auth
    # if username:
     #  auth = self.basic_auth(username, password)
     #  self.api_headers['Authorization'] = auth
       
  
  def post2(self, company, service_url, service, data):
    # response = requests.post(f"{self.base_url}/{self.company}/{self.service_url}/{self.service}", headers=Epicor.api_headers , data=jsons.dumps(data))
    response = requests.post(f"{self.base_url}/{company}/{service_url}/{service}", headers=Epicor.api_headers , json=data)  
    if response.status_code in (200, 201):
      pass
    elif response.status_code in (400, 401, 404):
      print ("Error of either 400, 401, 404")
      print (f"Error message json:\n{response.content}")
      print (f"Error message json:\n{response}")
      # breakpoint()
    elif response.status_code in (500, 501):
      print (f"Error message json:\n{response}")
      print ("Check closely format of input - numbers as string, dates as properly formatted ISO date strings, etc and json properly formats. Check for an array of objects (and not just an object)")
      print("Breaking...")
      breakpoint()
    return response
    
from Epicor2 import Epicor
import jsons

class GLJrnGrp(object):
  data = { 'Company' : "aaaaa",
           'GroupID' : "AABBCC",
           'BookMode' : 'S',
           'BookID' : "MAIN",
           'CurrencyCode' : "AUD",
           'RateGrpCode' : "MAIN",
           # JEDate : "2024-05-31"
           'FiscalYear' : 2024,
           'FiscalPeriod' : 11,
           'JournalCode' : "MJ",
           'FiscalCalendarID' : "MASTER",
           'COACode' : "MAIN",
           'Posted' : False,
           'RowMod' : 'A'
    }
  def __init__(self):
    pass
   
class GLJrnHed(object):
  data = {  'Company' : 'aaaaa',
 'FiscalCalendar' : 'MASTER',
 'FiscalYear'  : 2024,
 'FiscalPeriod'  : 11,
 'JournalNum' : 0,
 'Description'  : 'Journal Header Load',
 'JEDate' : '2024-05-31T00:00:00.000Z',
 'GroupID'  : 'AABBCC',
 'CurrencyCode': 'AUD',
 'EnteredBy'  : 'Sam Benson',
 'JournalCode' : 'MJ',
 'BookID' : 'MAIN',
 'TaxHandling' : '1',
 'TotDebit'  : 0,
 'TotCredit' : 0,
 # 'SysRevID' : None,
 # 'SysRowID' : None,
 'RateGrpCode' : 'MAIN',
 'RowMod'  : ''
 }

class GLJrnDtlMnl(object):
  data = { 
'Company' : 'aaaaa',  
'GroupID' : 'AABBCC',  
'JEDate' : '2024-05-31T00:00:00.000Z',
'FiscalYear' : 2024,  
'FiscalPeriod' : 11, 
'JournalNum' : '',  
'JournalLine' : 0,  
'Description' : 'Journal Line 1',
'TransAmt' : 110,   
'Posted' : False,
'SourceModule' : 1,
'COACode' : 'MAIN', 
'CommentText' : 'A Comments',
'GLAccount' : '11510-1004',
'SegValue1' : '11510',
'SegValue2' : '1004',
'BookID' : 'MAIN',
'DocTransAmt' : 0,
'CurrencyCode' : 'AUD',
'DebitAmount' : 110,
'CreditAmount' : 0,
'TotDebit' : 110,   
'TotCredit' : 0,
'TaxableAmtBookCurr' : 'AUD',
'TaxableAmtCurr' : 'AUD',
'TaxableAmtInBookCurr' : 110,
'TaxableAmtInTranCurr' : 110,
'TaxableLine' : '',  
'TaxLiability' : 'AUST',
'TaxLine' : False,
'RowMod' : 'A',
'TaxRate' : '',  
'TaxType' : '',  
'ReportingModule' : '', 
'TaxPointDate' : '',

  }
def make_group():
  group = GLJrnGrp().data
  load = { 'ds' : { "GLJrnGrp" : [{}]}} # , 'Company' : group.Company, 'FiscalPeriod' : group.FiscalPeriod, 'FiscalYear' : group.FiscalYear, 'JEDate' : group.JEDate } 
  
  resp = epicor.post2("aaaaa", "Erp.BO.GLJrnGrpSvc", "GetNewGLJrnGrp", load).json() 
  update = resp['parameters']['ds']
  update['GLJrnGrp'][1]['GroupID'] = group['GroupID']
  # update['GLJrnGrp'][1]['GroupID'] = group['GroupID']
  resp = epicor.post2("aaaaa", "Erp.BO.GLJrnGrpSvc", "Update", {'ds' : { 'GLJrnGrp' : [update['GLJrnGrp'][1]]}})
  return resp
  
def make_gl_journal_headers():
  header = GLJrnHed().data
  header['RowMod'] = 'A'
  response = epicor.post2("aaaaa", "Erp.BO.GLJournalEntrySvc", "GetNewGlJrnHedTran", { 'ds' : {'GLJrnHed' : [header]}, "GroupID" : 'AABBCC'}).json();
  preupdate = {'ds' :{ 'GLJrnHed'  : [header] } };
  response = epicor.post2("aaaaa", "Erp.BO.GLJournalEntrySvc", "PreUpdate", preupdate).json();
  update = {'ds' :{ 'GLJrnHed'  : [response['parameters']['ds']['GLJrnHed'][0]]} };
  response = epicor.post2("aaaaa", "Erp.BO.GLJournalEntrySvc", "Update", update).json();
  return response

def make_gl_journal_line(header):
  line = { 'ds' : { 'GLJrnHed' : [header]}, 'bookID' : 'MAIN', 'fiscalYear' : 2024,  'fiscalPeriod' : 11, 'fiscalYearSuffix' : '', 'journalCode' : 'MJ', 'journalNum' : header[0]['JournalNum'], 'journalLine' : 0} 
  breakpoint()
  response = epicor.post2("aaaaa", "Erp.BO.GLJournalEntrySvc", "GetNewGLJrnDtlMnl", line).json();
  # line = { 'ds' : { 'GLJrnHed' : [response['parameters']['ds']['GLJrnHed'][0]] , 'GLJrnDtlMnl' : [response['parameters']['ds']['GLJrnDtlMnl'][0]]}, 'iLineNum' : response['parameters']['ds']['GLJrnDtlMnl'][0]['JournalLine']}
  # breakpoint()
  # response = epicor.post2("aaaaa", "Erp.BO.GLJournalEntrySvc", "ChangeGlAcct1", line).json();
  print("After GetNewGLJrnDtlMnl")
  breakpoint()
  with open('response.txt', 'wt') as f:
    f.write(str(response))
    
  # temp = GLJrnDtlMnl().data
  # temp['JournalNum'] = header[0]['JournalNum']
  # preupdate = {'ds' :{ 'GLJrnHed'  : header , 'GLJrnDtlMnl' : [temp]  }}
  # response = epicor.post2("aaaaa", "Erp.BO.GLJournalEntrySvc", "PreUpdate", preupdate).json();
  update = {'ds' :{ 'GLJrnHed'  : [response['parameters']['ds']['GLJrnHed'][0]], 'GLJrnDtlMnl' : [response['parameters']['ds']['GLJrnDtlMnl'][0]]} }
  breakpoint()
  response = epicor.post2("aaaaa", "Erp.BO.GLJournalEntrySvc", "Update", update).json();
  breakpoint()
  return response
  
  
if __name__ == "__main__":
  epicor = Epicor(False, "aaaaa")
  # resp = make_group()
  resp = make_gl_journal_headers()
  resp = make_gl_journal_line(resp['parameters']['ds']['GLJrnHed'])
  print(resp)
  breakpoint()
  print("Debug")

Cheers

Somehow I have created 2927 empty GLJrnGrps.
They are all empty. There are no GroupID and no SysRowIDs.
I can’t find them using a BAQ so I have no easy way to update and remove them

Anyone have any ideas on how I might delete.
:slight_smile:

1 Like

Try a cross company baq, let’s see if they show up then.

Need to see what they look like so we can identify them.