# Good Receive

## Good Receive's Database

<table><thead><tr><th>UI Name</th><th>Database</th><th>Type</th><th>Remarks</th></tr></thead><tbody><tr><td>G/R No</td><td><pre><code>Doc
</code></pre></td><td><strong><code>String</code></strong></td><td>Avoid using the same <strong><code>G/R No</code></strong> to prevent overwrite.<br><br>E.g.: <code>GR-001234</code></td></tr><tr><td>G/R Key</td><td><pre><code>DocKey
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>271800</code></td></tr><tr><td>Last Modified</td><td><pre><code>LastModified
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>2024-12-20T08:57:37.557</code></td></tr><tr><td>Creditor</td><td><pre><code>CreditorCode
</code></pre></td><td><strong><code>String</code></strong></td><td><strong><code>Creditor</code></strong> must match existing <strong>creditor code</strong>, and they must be <strong>active</strong> state.<br><br>E.g.: <code>400-R002</code></td></tr><tr><td>Name</td><td><pre><code>CreditorName
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>BLUE SOFA PLT</code></td></tr><tr><td>Supplier DO No</td><td><pre><code>SupplierDONo
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>DO-100355</code></td></tr><tr><td>Address [Line 1]</td><td><pre><code>InvAddr1
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>NO 64, JALAN KP5</code></td></tr><tr><td>Address [Line 2]</td><td><pre><code>InvAddr2
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>KAWASAN INDUSTRIAL KOTA PUTERI</code></td></tr><tr><td>Address [Line 3]</td><td><pre><code>InvAddr3
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>48200, BATU ARANG SELANGOR</code></td></tr><tr><td>Address [Line 4]</td><td><pre><code>InvAddr4
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>BLOCK B, UNIT 12</code></td></tr><tr><td>Date</td><td><pre><code>DocDate
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>2024-12-20T00:00:00</code></td></tr><tr><td>Branch</td><td><pre><code>BranchCode
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>BR001</code></td></tr><tr><td>Display Term</td><td><pre><code>DisplayTerm
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>NET 60</code></td></tr><tr><td>Purchase Location</td><td><pre><code>PurchaseLocation
</code></pre></td><td><strong><code>String</code></strong></td><td><p>Must have existing <strong><code>Purchase Location</code></strong> in the accounting system.</p><p><br>E.g.: <code>PJ</code></p></td></tr><tr><td>Purchase Agent</td><td><pre><code>PurchaseAgent
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>AGENT001</code></td></tr><tr><td>Ship Via</td><td><pre><code>ShipVia
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>DHL</code></td></tr><tr><td>Ship Info</td><td><pre><code>ShipInfo
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>EXPRESS</code></td></tr><tr><td>Total (ex)</td><td><pre><code>TotalExTax
</code></pre></td><td><strong><code>Number</code></strong></td><td>E.g.: <code>5000</code></td></tr><tr><td>Inclusive</td><td><pre><code>InclusiveTax
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>T</code></td></tr><tr><td>Taxable Amount</td><td><pre><code>TaxableAmt
</code></pre></td><td><strong><code>Number</code></strong></td><td>E.g.: <code>4500</code></td></tr><tr><td>Tax</td><td><pre><code>Tax
</code></pre></td><td><strong><code>Number</code></strong></td><td>E.g.: <code>500</code></td></tr><tr><td>Currency</td><td><pre><code>CurrencyCode
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>USD</code></td></tr><tr><td>Rate</td><td><pre><code>CurrencyRate
</code></pre></td><td><strong><code>Number</code></strong></td><td>E.g.: <code>1.2</code></td></tr><tr><td>Local Total</td><td><pre><code>LocalNetTotal
</code></pre></td><td><strong><code>Number</code></strong></td><td>E.g.: <code>6000</code></td></tr><tr><td>Total</td><td><pre><code>NetTotal
</code></pre></td><td><strong><code>Number</code></strong></td><td>E.g.: <code>5500</code></td></tr><tr><td>Seq</td><td><pre><code>Seq
</code></pre></td><td><strong><code>Number</code></strong></td><td>E.g.: <code>17</code></td></tr><tr><td>Item Code</td><td><pre><code>ItemCode
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>RDS-5528 SOFA</code></td></tr><tr><td>Description</td><td><pre><code>Description
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>RDS CLOUD SOFA 5528</code></td></tr><tr><td>Description 2</td><td><pre><code>Desc2
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>L Shape(30", 40") / Col: Beetex HIVE GD 2035 - 05# Gold</code></td></tr><tr><td>Delivery Date</td><td><pre><code>DeliveryDate
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>2024-12-21T00:00:00</code></td></tr><tr><td>Location</td><td><pre><code>Location
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>PJ</code></td></tr><tr><td>UOM</td><td><pre><code>UOM
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>PCS</code></td></tr><tr><td>Quantity</td><td><pre><code>Qty
</code></pre></td><td><strong><code>Number</code></strong></td><td><p>Value must be <strong>number</strong>, and value <strong>cannot</strong> be <strong>negative.</strong></p><p>E.g.: <code>2</code></p></td></tr><tr><td>Unit Price</td><td><pre><code>UnitPrice
</code></pre></td><td><strong><code>Number</code></strong></td><td><p>Value must be <strong>number</strong>, and value <strong>cannot</strong> be <strong>negative.</strong></p><p>E.g.: <code>2500</code></p></td></tr><tr><td>Discount</td><td><pre><code>Discount
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>10%</code></td></tr><tr><td>C/N Amt.</td><td><pre><code>CNAmt
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>100</code></td></tr><tr><td>Subtotal</td><td><pre><code>SubTotal
</code></pre></td><td><strong><code>Number</code></strong></td><td>E.g.: <code>4500</code></td></tr><tr><td>Subtotal (ex)</td><td><pre><code>SubTotalExTax
</code></pre></td><td><strong><code>Number</code></strong></td><td>E.g.: <code>4000</code></td></tr><tr><td>Detail Tax</td><td><pre><code>DtlTax
</code></pre></td><td><strong><code>Number</code></strong></td><td>E.g.: <code>500</code></td></tr><tr><td>Ref Doc No</td><td><pre><code>FromDocNo
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>PO-001638</code></td></tr><tr><td>UDF Desc 2</td><td><pre><code>UDF_Desc2
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>Special Instructions</code></td></tr></tbody></table>

## Good Receive's Sample Code

{% hint style="warning" %}
Remember to change to the **correct field** before proceeding to run **ANY** script.
{% endhint %}

{% tabs %}
{% tab title="SQL Script" %}
{% hint style="info" %}
This is a sample SQL, may not be as same as your database.
{% endhint %}

```sql
SELECT TOP (10)
    Doc AS Document,
    DocKey AS DocumentKey,
    LastModified,
    CreditorCode,
    CreditorName,
    SupplierDONo,
    InvAddr1,
    InvAddr2,
    InvAddr3,
    InvAddr4,
    DocDate,
    BranchCode,
    DisplayTerm,
    PurchaseLocation,
    PurchaseAgent,
    ShipVia,
    ShipInfo,
    TotalExTax,
    InclusiveTax,
    TaxableAmt,
    Tax,
    CurrencyCode,
    CurrencyRate,
    LocalNetTotal,
    NetTotal,
    Seq,
    ItemCode,
    Description,
    Desc2,
    DeliveryDate,
    Location,
    UOM,
    Qty,
    UnitPrice,
    Discount,
    CNAmt,
    SubTotal,
    SubTotalExTax,
    DtlTax,
    FromDocNo,
    UDF_Desc2,
    LastModified
FROM GoodReceives
WHERE LastModified > "{LAST_MODIFIED_DATE_TIME}";
```

{% endtab %}

{% tab title="jobs.json" %}
{% hint style="warning" %}
In order to sync, you must include **`LastModified`** in **`SELECT`**
{% endhint %}

```json
"SQLSync": [
  {
    "name": "AutoCount to Inistate",
    "enabled": false,
    "connectionString": "Data Source={SERVER};Initial Catalog={DATABASE};User Id={DB_USERNAME};Password={DB_PASSWORD};",
    "hook": "https://api.inistate.com/api/automationHook/hook/{MODULE-ID}-{LOGIC-NAME}",
    "sql": "SELECT AccNo, CompanyName, Address1, Address2, Address3, Address4, Phone1, DisplayTerm, EmailAddress, SalesAgent, LastModified \nFROM Debtor \nWHERE LastModified > @date",
    "lastSync": "{LAST-SYNC-DATE-TIME}",
    "start": null
  }
]
```

{% endtab %}

{% tab title="Logic Script" %}
{% hint style="info" %}
To find `{fieldName}`, you are required to have access to **Alpha** or use **Network** in Developer Tools `[F12]`.
{% endhint %}

{% code fullWidth="true" %}

```python
#debug('test', inputs)

moduleName = '{YOUR-MODULE-NAME}'
inistateKeyField = 'DocumentId'
keyField = 'Doc'
modifiedDateField = 'LastModified'
fields = [['DocumentId', 'Doc'],['LastModified', 'LastModified']]
inistateFields = []
tableField = 'Items'
tableColumns = ['Seq','ItemCode','Description','Desc2','DeliveryDate','Location','UOM','Qty','UnitPrice','Discount','CNAmt','SubTotal','SubTotalExTax','DtlTax','FromDocNo','UDF_Desc2']

def getFlatten(list, table):
    details = [dict(Line=y, Document=x) for x in list for y in x[table]]
    return details

def createLine(x):
    item = JObject()
    main = JObject.FromObject(x[0])
    
    for field in main:
        if not tableColumns.Contains(field.Name):
            item[field.Name] = main[field.Name]
        
    item['items'] = JArray()
        
    for itemRow in x:
        rowJSON = JObject()
        for field in tableColumns:
            rowJSON[field] = itemRow[field]
        item['items'].Add(rowJSON)
        
    return item

def productAddToSync(product):
    if product is not None:
        form = Module('{YOUR-MODULE-NAME}').execute('Set To Sync', product)
        form['To Sync'] = True
        Module('{YOUR-MODULE-NAME}').submit(product, 'Set To Sync', form)

result = list(inputs["list"]).GroupBy(lambda x: x[keyField].ToString()).Select(lambda x: createLine(x)).ToList()

for item in result:
    entry = Module('{YOUR-MODULE-NAME}').find({ 'Dynamic.Extension.{fieldName}': item['Doc'] })
    
    # debug('valid', entry['SyncDateTime'])
    # debug('valid time', item['LastModified'])
    form = Module('{YOUR-MODULE-NAME}').execute('sync', entry)
    form['{YOUR-CREDITOR}'] = item['CreditorCode']
    form['{YOUR-NAME}'] = item['CreditorName']
    form['{YOUR-G/R NO}'] = item['Doc']
    form['{YOUR-ADDRESS1}'] = item['InvAddr1']
    form['{YOUR-ADDRESS2}'] = item['InvAddr2']
    form['{YOUR-ADDRESS3}'] = item['InvAddr3']
    form['{YOUR-ADDRESS4}'] = item['InvAddr4']
    form['{YOUR-SUPPLIER D/O NO}'] = item['SupplierDONo']
    form['{YOUR-DATE}'] = item['DocDate']
    form['{YOUR-BRANCH}'] = item['BranchCode']
    form['{YOUR-CREDIT TERM}'] = item['DisplayTerm']
    form['{YOUR-PURCHASE LOCATION}'] = item['PurchaseLocation']
    form['{YOUR-PURCHASE AGENT}'] = item['PurchaseAgent']
    form['{YOUR-SHIP VIA}'] = item['ShipVia']
    form['{YOUR-SHIP INFO}'] = item['ShipInfo']
    
    form['{YOUR-SUBTOTAL (EX)}'] = item['TotalExTax']
    form['{YOUR-INCLUSIVE?}'] = True if item['InclusiveTax'] != "F" else False
    form['{YOUR-TAXABLE AMOUNT}'] = item['TaxableAmt']
    form['{YOUR-TAX}'] = item['Tax']
    form['{YOUR-CURRENCY}'] = item['CurrencyCode']
    form['{YOUR-RATE}'] = item['CurrencyRate']
    form['{YOUR-LOCAL TOTAL}'] = item['LocalNetTotal']
    form['{YOUR-TOTAL}'] = item['NetTotal']
    debug('Tax', item)
    # handle table
    lines = list(item['items']).ToList().OrderBy(lambda x: Convert.ToInt32(x['Seq'])).ToList()
    
    while len(form['{YOUR-GOODS INFORMATION}']) > len(lines) :
        last = form['{YOUR-GOODS INFORMATION}'].Last()
        productAddToSync(last['Item Code'])
        formLine = form.remove('{YOUR-GOODS INFORMATION}',last)
    
    for line in lines:
        # create if none
        if len(form['{YOUR-GOODS INFORMATION}']) <= lines.IndexOf(line):
            formLine = form.add('{YOUR-GOODS INFORMATION}')
        else :
            formLine = form['{YOUR-GOODS INFORMATION}'][lines.IndexOf(line)]
            
        # assign value to table row
        product = Module('Product').find({ 'Dynamic.Extension.{fieldName}': str(line['ItemCode'])  })
        
        if product is not None:
            if formLine['{YOUR-ITEM CODE}'].Id > 0 and formLine['{YOUR-ITEM CODE}'] != str(line['ItemCode']) and entry is not None :
                productAddToSync(formLine['{YOUR-ITEM CODE}'])
            formLine['{YOUR-ITEM CODE}'] = product
            
        formLine['{YOUR-DESCRIPTION}'] = line['Description']
        formLine['{YOUR-DESCRIPTION 2}'] = line['Desc2']
        formLine['{YOUR-DELIVERY DATE}'] = line['DeliveryDate']
        formLine['{YOUR-LOCATION}'] = line['Location']
        formLine['{YOUR-UOM}'] = line['UOM']
        formLine['{YOUR-QTY}'] = line['Qty']
        formLine['{YOUR-UNIT PRICE}'] = line['UnitPrice']
        formLine['{YOUR-DISCOUNT}'] = line['Discount']
        formLine['{YOUR-C/N AMT.}'] = line['CNAmt']
        formLine['{YOUR-SUBTOTAL}'] = line['SubTotal']
        formLine['{YOUR-TAX}'] = line['DtlTax']
        formLine['{YOUR-TOTAL (EX)}'] = line['SubTotalExTax']
        formLine['{YOUR-TOTAL (INC)}'] = Convert.ToInt32(line['SubTotalExTax'] if line['SubTotalExTax'] != None else 0) + Convert.ToInt32(line['DtlTax'] if line['DtlTax'] != None else 0) #no field in Autocount record total include tax, need add 2 value
        formLine['{YOUR-FROM DOC. NO.}'] = line['FromDocNo']
        formLine['{YOUR-DESC2}'] = line['UDF_Desc2']
        
    # debug('form', form)
    Module('{YOUR-MODULE-NAME}').submit(entry, form)
    
    after = Module('{YOUR-MODULE-NAME}').find({ 'Dynamic.Extension.{fieldName}': item['Doc'] })
    if after is not None:
        #Get Distinct PO number in GRN
        withPO = filter(lambda x: ('PO' in x['From Doc. No.']), after['{YOUR-GOODS INFORMATION}'])
        sortByPO = sorted(withPO, key=lambda x: x['From Doc. No.'])
        groupByPO = [dict(Key=ckey, List=list(cgroup)) for ckey, cgroup in groupby(sortByPO, lambda x: x['From Doc. No.'])]
    
        for po in groupByPO:
            #Get All Good Receive realated to the PO 
            grn = Module('{YOUR-MODULE-NAME}').findAll({'Dynamic.Extension.{fieldName}': po['Key']})
            items = getFlatten(grn, '{YOUR-GOODS INFORMATION}')
            sortByItem = sorted(items, key=lambda x: x['Line']['Item Code'])
            groupByItem = [dict(Key=ckey, List=list(cgroup)) for ckey, cgroup in groupby(sortByItem, lambda x: {"Item Code" : x['Line']['Item Code'], "PONumber" : x['Line']['From Doc. No.'] })]
            
            # debug('po', po['Key'])
            p = Module('{YOUR-MODULE-NAME}').find({'$and': [{'Dynamic.Extension.{fieldName}': po['Key']}]} )
            if p is not None:
                form2 = Module('{YOUR-MODULE-NAME}').execute('Receive', p)
                u = 0
                sortPOItem = sorted(form2['Main'], key=lambda x: x['Item Code'])
                groupPOItem = [dict(Key=ckey, List=list(cgroup)) for ckey, cgroup in groupby(sortPOItem, lambda x: x['Item Code'])]
                for r in groupPOItem:
                    goodReceives = next((x for x in groupByItem if x['Key']['Item Code'] == r['Key'] and x['Key']['PONumber'] == po['Key']), None)
                    if goodReceives is not None:
                        totalReceived = sum(x['Line']['Qty'] for x in goodReceives['List'])
                        if totalReceived != sum(x['Received'] for x in r['List']):
                            qty = totalReceived
                            for l in r['List']:
                                if qty > 0:
                                    if qty >= l['Qty']:
                                        l['Received'] = l['Qty']
                                        qty = qty - l['Qty']
                                    else:
                                        l['Received'] = qty
                                        qty = 0
                            u = 1
                    else:
                        for l in r['List']:
                            l['Received'] = 0
                        u = 1
                if u == 1:
                    result2 = Module('{YOUR-MODULE-NAME}').submit(p, 'Receive', form2)
                    # debug('result2', result2)
                    debug('Impacted PO', po['Key'])

    
debug('result', result)
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://inistate.gitbook.io/home/advanced/integration/accounting-2/good-receive.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
