# Invoice

## Invoice's Database

<table data-full-width="false"><thead><tr><th width="111">UI Name</th><th width="177">Database</th><th width="99.5556640625">Type</th><th width="249">Remarks</th><th>Important</th></tr></thead><tbody><tr><td>Debtor</td><td><pre><code>debtorCode
</code></pre></td><td><strong><code>String</code></strong></td><td><strong><code>Debtor</code></strong> must match existing <strong>debtor code</strong>, and they must be <strong>active</strong> state.<br><br>E.g.: <code>300-A001</code></td><td></td></tr><tr><td>Invoice No</td><td><pre><code>docNo
</code></pre></td><td><strong><code>String</code></strong></td><td><p>Avoid using the same <strong><code>Invoice No</code></strong> to prevent overwrite.</p><p></p><p>*Document Id or Running Number<br><br>E.g.: <code>INV00001</code></p></td><td></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-11-27T00:00:00+08:00</code></td><td></td></tr><tr><td>Sales Location</td><td><pre><code>salesLocation
</code></pre></td><td><strong><code>String</code></strong></td><td>Must have existing <strong><code>Sales Location</code></strong> in the accounting system.<br><br>E.g.: <code>HQ</code></td><td></td></tr><tr><td>Credit Term</td><td><pre><code>displayTerm
</code></pre></td><td><strong><code>String</code></strong></td><td><strong><code>Credit Term</code></strong> must match the same in the accounting system<br><br>E.g.: <code>C.O.D.</code></td><td></td></tr><tr><td>Description</td><td><pre><code>Description
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>INVOICE</code></td><td>Limit 80 Characters Max</td></tr><tr><td>Inclusive?</td><td><pre><code>inclusiveTax
</code></pre></td><td><strong><code>Boolean</code></strong></td><td>E.g.: <code>False</code></td><td></td></tr><tr><td>Rate</td><td><pre><code>currencyRate
</code></pre></td><td><strong><code>Decimal</code></strong></td><td>E.g.: <code>1.234</code></td><td></td></tr><tr><td>Table Item</td><td><pre><code>details
</code></pre></td><td><strong><code>Array</code></strong></td><td><a href="#invoices-table-item">Refer below</a></td><td></td></tr></tbody></table>

## Invoice's Table Item

<table><thead><tr><th>UI Name</th><th>Database</th><th>Type</th><th>Remarks</th></tr></thead><tbody><tr><td>Item Code</td><td><pre><code>itemCode
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>A001</code></td></tr><tr><td>Acc. No.</td><td><pre><code>accNo
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>500-0123</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>PRODUCT - CL14</code></td></tr><tr><td>D/O Number</td><td><pre><code>ourDONo
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>DO-123-456</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>UNIT</code></td></tr><tr><td>Location</td><td><pre><code>location
</code></pre></td><td><strong><code>String</code></strong></td><td><p>Must have existing <strong><code>Location</code></strong> in the accounting system.</p><p></p><p>E.g.: <code>HQ</code></p></td></tr><tr><td>Qty</td><td><pre><code>qty
</code></pre></td><td><strong><code>Decimal</code></strong></td><td><p>Value must be <strong>number</strong>, and value <strong>cannot</strong> be <strong>negative.</strong></p><p></p><p>E.g.: <code>10.0</code></p></td></tr><tr><td>Unit Price</td><td><pre><code>unitPrice
</code></pre></td><td><strong><code>Decimal</code></strong></td><td><p>Value must be <strong>number</strong>, and value <strong>cannot</strong> be <strong>negative.</strong></p><p></p><p>E.g.: <code>10.0</code></p></td></tr><tr><td>Tax Adjustment</td><td><pre><code>taxAdjustment
</code></pre></td><td><strong><code>String</code></strong></td><td>Value must be <strong>None</strong></td></tr><tr><td>Tax Code</td><td><pre><code>taxCode
</code></pre></td><td><strong><code>String</code></strong></td><td>E.g.: <code>SV-01</code></td></tr></tbody></table>

### Additional for E-Invoice

<table><thead><tr><th width="127.5555419921875">Name</th><th width="174.3359375">Field</th><th width="178.3707275390625">Type</th><th>Remarks</th></tr></thead><tbody><tr><td>E-Invoice Start Date</td><td><pre><code><strong>e_inv_start_date
</strong></code></pre></td><td><strong><code>DateTime</code></strong></td><td><code>DateTime(2026,1,1)</code><br>*Login to AutoCount,<br> go to the <code>e-Invoice tab</code> → <code>e-Invoice Setting</code> → <strong>tick</strong> "<code>Enable e-Invoice</code>" →Start Date: <code>01/01/2026</code></td></tr><tr><td>Cancelled</td><td><pre><code>cancelled
</code></pre></td><td><strong><code>Boolean</code></strong></td><td>Pass <code>true</code> to <strong><code>void the Invoice</code></strong></td></tr><tr><td>Draft</td><td><pre><code>draft
</code></pre></td><td><strong><code>Boolean</code></strong></td><td>Pass <code>true</code> to allow Invoice <strong><code>Save as Draft</code></strong> . (invoice will not be finalized).</td></tr><tr><td>Submit E-Invoice</td><td><pre><code>submitEInvoice
</code></pre></td><td><strong><code>Boolean</code></strong></td><td>Pass <code>true</code> to check on the <strong><code>Submit e-Invoice?</code></strong></td></tr></tbody></table>

## Invoice's Sample Code

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

{% tabs %}
{% 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 %}

<pre class="language-python" data-full-width="true"><code class="lang-python">import clr
clr.AddReference("Newtonsoft.Json")
clr.AddReference("System.Net")
clr.AddReference("System.IO")

from System.Text import *
from Newtonsoft.Json import *
from Newtonsoft.Json.Linq import *
from System import *

clr.AddReference("System.Drawing")
from System.Drawing import Bitmap, Image
from System.Drawing.Imaging import ImageFormat
from System.IO import MemoryStream, StreamWriter
from System.Net import WebClient
import binascii
from System import BitConverter

# search
documentList = Module("{YOUR-MODULE-NAME}").findAll(
    {
        "Audit.UpdatedDate": {"$gt": Inputs["lastSync"]},
        "Audit.UpdatedBy": {"$ne": "External"},
        'Dynamic.Extension.{fieldName}': {'$in': [None, '']}, #Error Message
        "Dynamic.Extension.{fieldName}": {"$eq" : None }, #E-Invoice Validated Date
        "Dynamic.Extension.{fieldName}": {"$ne": None}, #Business logic
    }
)
debug("documentList", documentList)

resultList = []
# E-Invoice implementation start date
e_inv_start_date = DateTime(2026, 1, 1)

def prepareRow(x):
    row = JObject()
    # row["itemCode"] = x["{YOUR-ITEM-CODE}"]
    payloadData["payload"]["docNo"] = data.DocumentId
    # row["ourDONo"] = x["{YOUR-DO-NO}"]
    # row["location"] = x["{YOUR-LOCATION}"]
    row["description"] = x["{YOUR-DESCRIPTION}"].ToString()
    row["qty"] = x["{YOUR-QTY}"]
    row["uom"] = x["{YOUR-UOM}"]
    row["unitPrice"] = x["{YOUR-UNIT-PRICE}"] * x["{YOUR-EXCHANGE-RATE}"]
    row["subtotal"] = x['YOUR-SUBTOTAL']
    row['classification'] = str(x['YOUR-CLASSIFICATION'])
    row["taxAdjustment"] = None
    if x["Tax Code"].Id != 0:
        row["taxCode"] = x['YOUR-TAX-CODE']['YOUR-TAX-CODE']
    return row


def preparePayload(data):
    payloadData = JObject()
    payloadData["type"] = "ARInvoice"
    payloadData["cancelled"] = data["{IS-YOUR-DOC-CANCELLED}"]
    payloadData["payload"] = JObject()
    
    # Only process e-Invoice logic for invoices issued after e-Invoice start date
    if data['Invoice Date'] > e_inv_start_date:
        payloadData["draft"] = True
        if data['E-Invoice Validated Date'] is not None:
            payloadData["draft"] = False
        
        payloadData["payload"]["submitEInvoice"] = True    

    if data['Code'] != None and data['Code'] != 0:
        payloadData["payload"]["docKey"] = data['YOUR-CODE']
    
    
    payloadData["payload"]["debtorCode"] = data["{YOUR-DEBTOR-CODE}"]
    payloadData["payload"]["docNo"] = None if data['{YOUR-DOC-NO}'] == "" or data['{YOUR-DOC-NO}'] is None else data['{YOUR-DOC-NO}']
    #payloadData["payload"]["docNo"] = data.DocumentId
    payloadData["payload"]["docDate"] = data["{YOUR-DOC-DATE}"]
    payloadData["payload"]["salesLocation"] = data["{YOUR-SALES-LOCATION}"]
<strong>    payloadData["payload"]["description"] = data['YOUR-TRANSACTION-DESCRIPTION'][:80]
</strong><strong>    payloadData["payload"]["inclusiveTax"] = False if data['YOUR-TAX-INCLUSIVE?'] != True else True
</strong>    payloadData["payload"]["displayTerm"] = data["{YOUR-TERM}"]
    payloadData["payload"]["currencyRate"] = Convert.ToDecimal(data['YOUR-EXCHANGE-RATE']) if data['YOUR-EXCHANGE-RATE'] is not None else Decimal(0)

<strong>    payloadData["payload"]["details"] = JArray.FromObject(data['YOUR-DETAILS'].Select(lambda x: prepareRow(x)))
</strong>
    payloadData["LastModified"] = data.UpdatedDate
    return payloadData


# end of added
for entry in documentList:
    payloadData = preparePayload(entry)
    if (
        payloadData["payload"]["debtorCode"] != None
        and payloadData["payload"]["debtorCode"] != ""
    ):
        resultList.append(payloadData)
    # debug('payloadData', payloadData)


# debug('done', resultList)
outputs["results"] = JArray.FromObject(resultList)
debug("result", resultList)
</code></pre>

{% endtab %}

{% tab title="Extras" %}

```
def image_to_hex(image_url):
    web_client = WebClient()
    image_data = web_client.DownloadData(image_url)

    with MemoryStream(image_data) as image_stream:
        bitmap = Bitmap(image_stream)
        # Resize the image
        original_width = bitmap.Width
        original_height = bitmap.Height
        max_width = 240.0
        max_height = 240.0
        # Calculate new dimensions preserving the aspect ratio
        ratio = min(max_width / original_width, max_height / original_height)
        new_width = int(original_width * ratio)
        new_height = int(original_height * ratio)
        debug("new_width", new_width)

        resized_bitmap = bitmap.GetThumbnailImage(
            new_width, new_height, None, IntPtr.Zero
        )

        # Convert the image to PNG (or other supported formats)
        png_stream = MemoryStream()
        # resized_bitmap.Save(png_stream, ImageFormat.Png)
        png_bytes = png_stream.ToArray()

        # Convert PNG byte array to hexadecimal string
        png_hex = "".join("{:02x}".format(b) for b in png_bytes)

        # Create RTF content with the embedded PNG image
        rtf = []
        rtf.append(
            r"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Arial;}}"
        )
        rtf.append(r"\viewkind4\uc1")

        # image start
        stream = MemoryStream()
        resized_bitmap.Save(stream, ImageFormat.Bmp)  # Save as BMP
        stream.Position = 0  # Reset stream position

        # Read bytes and convert to hex
        img_bytes = stream.ToArray()
        # debug('img_bytes', img_bytes)
        # debug('here', 'here1')
        # hex_string = binascii.hexlify(img_bytes).decode('ascii')
        hex_string = BitConverter.ToString(img_bytes).Replace("-", "").ToLower()

        # Write the RTF content to a file
        return hex_string
        
    
```

{% endtab %}
{% endtabs %}
