Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More logic for invoice handling #5

Merged
merged 3 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion oda_wd_client/base/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,19 @@ class WorkdayReferenceBaseModel(BaseModel):
workday_parent_id: str | None = None
workday_parent_type: str | None = None

# This is the name of the class in Workday. Usually ends with "Object" (i.e. "SupplierObject")
_class_name: str | None = None

def wd_object(
self,
client,
class_name: str,
class_name: str | None = None,
) -> sudsobject.Object:
class_name = class_name or self._class_name
assert (
class_name
), "WD Class name must be supplied on class or call to wd_object"

ref_obj = client.factory(f"ns0:{class_name}Type")
id_obj = client.factory(f"ns0:{class_name}IDType")
id_obj.value = self.workday_id
Expand Down
2 changes: 2 additions & 0 deletions oda_wd_client/service/financial_management/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ class ConversionRateType(BaseModel):


class Currency(WorkdayReferenceBaseModel):
_class_name = "CurrencyObject"
workday_id: str = Field(max_length=3, alias="currency_code")
workday_id_type: Literal["Currency_ID"] = "Currency_ID"
description: str | None = None
retired: bool = False


class Company(WorkdayReferenceBaseModel):
_class_name = "CompanyObject"
workday_id: str
workday_id_type: Literal["Company_Reference_ID"] = "Company_Reference_ID"
name: str
Expand Down
47 changes: 45 additions & 2 deletions oda_wd_client/service/resource_management/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@


class TaxApplicability(WorkdayReferenceBaseModel):
_class_name = "Tax_ApplicabilityObject"
workday_id: str
workday_id_type: Literal["Tax_Applicability_ID"] = "Tax_Applicability_ID"
# Code is human-readable text but not critical, so we default to empty string
Expand All @@ -18,11 +19,19 @@ class TaxApplicability(WorkdayReferenceBaseModel):


class TaxOption(WorkdayReferenceBaseModel):
_class_name = "Tax_OptionObject"
workday_id: str
workday_id_type: Literal["Tax_Option_ID"] = "Tax_Option_ID"


class TaxCode(WorkdayReferenceBaseModel):
_class_name = "Tax_CodeObject"
workday_id: str
workday_id_type: Literal["Tax_Code_ID"] = "Tax_Code_ID"


class Supplier(WorkdayReferenceBaseModel):
_class_name = "SupplierObject"
workday_id: str
workday_id_type: Literal["Supplier_ID"] = "Supplier_ID"
reference_id: str | None
Expand Down Expand Up @@ -63,9 +72,44 @@ class Supplier(WorkdayReferenceBaseModel):
tax_id_us: str | None


class TaxRate(WorkdayReferenceBaseModel):
_class_name = "Tax_RateObject"
workday_id_type: Literal["Tax_Rate_ID"] = "Tax_Rate_ID"


class TaxRecoverability(WorkdayReferenceBaseModel):
_class_name = "Tax_RecoverabilityObject"
workday_id_type: Literal[
"Tax_Recoverability_Object_ID"
] = "Tax_Recoverability_Object_ID"


class SpendCategory(WorkdayReferenceBaseModel):
_class_name = "Spend_CategoryObject"
workday_id_type: Literal["Spend_Category_ID"] = "Spend_Category_ID"


class TaxRateOptionsData(BaseModel):
tax_rate: TaxRate
tax_recoverability: TaxRecoverability = TaxRecoverability(
workday_id="Fully_Recoverable"
)
tax_option: TaxOption = TaxOption(workday_id="CALC_TAX_DUE")


class CostCenter(WorkdayReferenceBaseModel):
_class_name = "Accounting_WorktagObject"
workday_id_type: Literal["Cost_Center_Reference_ID"] = "Cost_Center_Reference_ID"


class SupplierInvoiceLine(BaseModel):
order: int | None
description: str | None
tax_rate_options_data: TaxRateOptionsData
tax_applicability: TaxApplicability
tax_code: TaxCode
spend_category: SpendCategory
cost_center: CostCenter
amount: Decimal = Field(max_digits=18, decimal_places=3)


Expand All @@ -78,8 +122,7 @@ class SupplierInvoice(BaseModel):
due_date: date
total_amount: Decimal = Field(max_digits=26, decimal_places=6)
tax_amount: Decimal = Field(max_digits=26, decimal_places=6)
# ENTER_TAX_DUE is "Enter tax due to supplier", which is needed to manually set tax amount in invoices
tax_option: TaxOption = TaxOption(workday_id="ENTER_TAX_DUE")
tax_option: TaxOption

lines: list[SupplierInvoiceLine]

Expand Down
47 changes: 26 additions & 21 deletions oda_wd_client/service/resource_management/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
Supplier,
SupplierInvoice,
SupplierInvoiceLine,
TaxApplicability,
)

# Mapping the Workday tax ID types to canonical names used by our model
Expand Down Expand Up @@ -130,23 +129,35 @@ def workday_supplier_to_pydantic(data: dict) -> Supplier:
)


def _get_wd_invoice_lines_from_invoice(client, lines: list[SupplierInvoiceLine]):
def _get_wd_invoice_lines_from_invoice(
client, lines: list[SupplierInvoiceLine]
) -> list[sudsobject.Object]:
returned_lines = []

for line in lines:
wd_line = client.factory("ns0:Supplier_Invoice_Line_Replacement_DataType")
# wd_tax = client.factory("ns0:Tax_Rate_Options_DataType")
wd_line.Supplier_Invoice_Line_ID = line.order
wd_line.Item_Description = line.description
wd_line.Extended_Amount = line.amount

# wd_line.Tax_Rate_Options_Data = wd_tax
test_applicability = TaxApplicability(
workday_id="NOR_Domestic_Purchase_of_Goods_and_Services"
)
wd_line.Tax_Applicability_Reference = test_applicability.wd_object(
client, "Tax_ApplicabilityObject"
wd_line.Spend_Category_Reference = line.spend_category.wd_object(client)

# Tax options
wd_tax = client.factory("ns0:Tax_Rate_Options_DataType")
tax_opts = line.tax_rate_options_data
wd_tax.Tax_Rate_1_Reference = tax_opts.tax_rate.wd_object(client)
wd_tax.Tax_Recoverability_1_Reference = tax_opts.tax_recoverability.wd_object(
client
)
wd_tax.Tax_Option_1_Reference = tax_opts.tax_option.wd_object(client)
wd_line.Tax_Rate_Options_Data = wd_tax

# Tax code
wd_line.Tax_Applicability_Reference = line.tax_applicability.wd_object(client)
wd_line.Tax_Code_Reference = line.tax_code.wd_object(client)

# Worktags
wd_line.Worktags_Reference.append(line.cost_center.wd_object(client))

returned_lines.append(wd_line)

return returned_lines
Expand All @@ -167,20 +178,14 @@ def pydantic_supplier_invoice_to_workday(
invoice_data.Locked_in_Workday = True

invoice_data.Invoice_Number = invoice.invoice_number
invoice_data.Company_Reference = invoice.company.wd_object(client, "CompanyObject")
invoice_data.Currency_Reference = invoice.currency.wd_object(
client, "CurrencyObject"
)
invoice_data.Supplier_Reference = invoice.supplier.wd_object(
client, "SupplierObject"
)
invoice_data.Default_Tax_Option_Reference = invoice.tax_option.wd_object(
client, "Tax_OptionObject"
)
invoice_data.Company_Reference = invoice.company.wd_object(client)
invoice_data.Currency_Reference = invoice.currency.wd_object(client)
invoice_data.Supplier_Reference = invoice.supplier.wd_object(client)
invoice_data.Default_Tax_Option_Reference = invoice.tax_option.wd_object(client)
invoice_data.Invoice_Date = str(invoice.invoice_date)
invoice_data.Due_Date_Override = str(invoice.due_date)
invoice_data.Control_Amount_Total = invoice.total_amount
invoice_data.Tax_Amount = invoice.tax_amount
# invoice_data.Tax_Amount = invoice.tax_amount
# invoice_data.Attachment_Data = _get_wd_attachment_data_from_invoice(invoice)
invoice_data.Invoice_Line_Replacement_Data = _get_wd_invoice_lines_from_invoice(
client, invoice.lines
Expand Down
16 changes: 14 additions & 2 deletions oda_wd_client/types/resource_management.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
from oda_wd_client.service.resource_management.types import (
CostCenter,
SpendCategory,
Supplier,
SupplierInvoice,
SupplierInvoiceLine,
TaxApplicability,
TaxCode,
TaxOption,
TaxRate,
TaxRateOptionsData,
TaxRecoverability,
)

__all__ = [
"TaxApplicability",
"TaxOption",
"CostCenter",
"SpendCategory",
"Supplier",
"SupplierInvoice",
"SupplierInvoiceLine",
"TaxApplicability",
"TaxCode",
"TaxOption",
"TaxRate",
"TaxRateOptionsData",
"TaxRecoverability",
]
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "oda-wd-client"
version = "0.0.1"
version = "0.0.2"
description = "A library for interacting with Workday from Python"
authors = [
"Karl Fredrik Haugland <karlfredrik.haugland@oda.com>",
Expand Down
Loading