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

Add basic structs for MX fuel complement #192

Closed
wants to merge 14 commits into from
Closed
152 changes: 152 additions & 0 deletions build/schemas/regimes/mx/fuel-complement.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://gobl.org/draft-0/regimes/mx/fuel-complement",
"$ref": "#/$defs/FuelComplement",
"$defs": {
"FuelComplement": {
"properties": {
"wallet_account_number": {
"type": "string",
"title": "Wallet Account Number",
"description": "Customer's e-wallet account number"
},
"lines": {
"items": {
"$ref": "#/$defs/FuelLine"
},
"type": "array",
"title": "Lines",
"description": "List of fuel purchases made with the customer's e-wallets"
},
"totals": {
"$ref": "#/$defs/FuelTotals",
"title": "Totals",
"description": "Summary of all the purchases totals, including taxes (calculated)",
"calculated": true
}
},
"type": "object",
"required": [
"wallet_account_number",
"lines",
"totals"
],
"description": "FuelComplement carries the data to produce the CFDI's \"Complemento de Estado de Cuenta de Combustibles para Monederos Electrónicos\" (version 1.2 revision B) which provides detailed information about fuel purchases made with electronic wallets."
},
"FuelItem": {
"properties": {
"unit": {
"$ref": "https://gobl.org/draft-0/org/unit",
"title": "Unit",
"description": "Reference unit of measure used in the price and the quantity"
},
"type": {
"$ref": "https://gobl.org/draft-0/cbc/code",
"title": "Type",
"description": "Type of fuel (c_ClaveTipoCombustible codes)"
},
"name": {
"type": "string",
"title": "Name",
"description": "Name of the fuel"
},
"price": {
"$ref": "https://gobl.org/draft-0/num/amount",
"title": "Price",
"description": "Base price of a single unit of the fuel"
}
},
"type": "object",
"required": [
"unit",
"name",
"price"
],
"description": "FuelItem provides the details of the fuel purchased."
},
"FuelLine": {
"properties": {
"wallet_id": {
"$ref": "https://gobl.org/draft-0/cbc/code",
"title": "Wallet Identifier",
"description": "Identifier of the e-wallet used to make the purchase"
},
"purchase_date": {
"$ref": "https://gobl.org/draft-0/cal/date-time",
"title": "Purchase Date",
"description": "Date and time of the purchase"
},
"purchaser_tax_id": {
"$ref": "https://gobl.org/draft-0/cbc/code",
"title": "Purchaser's Tax ID",
"description": "Tax ID (RFC) of the purchaser"
},
"service_station_code": {
"$ref": "https://gobl.org/draft-0/cbc/code",
"title": "Service Station Code",
"description": "Code of the service station where the purchase was made"
},
"quantity": {
"$ref": "https://gobl.org/draft-0/num/amount",
"title": "Quantity",
"description": "Amount of fuel units purchased"
},
"item": {
"$ref": "#/$defs/FuelItem",
"title": "Item",
"description": "Details about the fuel purchased"
},
"purchase_id": {
"$ref": "https://gobl.org/draft-0/cbc/code",
"title": "Purchase Identifier",
"description": "Identifier of the purchase (folio)"
},
"total": {
"$ref": "https://gobl.org/draft-0/num/amount",
"title": "Total",
"description": "Result of quantity multiplied by the item's price (calculated)",
"calculated": true
},
"taxes": {
"$ref": "https://gobl.org/draft-0/tax/set",
"title": "Taxes",
"description": "Map of taxes applied to the purchase"
}
},
"type": "object",
"required": [
"wallet_id",
"purchase_date",
"purchaser_tax_id",
"service_station_code",
"quantity",
"item",
"purchase_id",
"total",
"taxes"
],
"description": "FuelLine represents a single fuel purchase made with an e-wallet issued by the invoice's supplier to the invoice's customer."
},
"FuelTotals": {
"properties": {
"total": {
"$ref": "https://gobl.org/draft-0/num/amount",
"title": "Total",
"description": "Sum of all line sums"
},
"total_with_tax": {
"$ref": "https://gobl.org/draft-0/num/amount",
"title": "Total with Tax",
"description": "Grand total after taxes have been applied."
}
},
"type": "object",
"required": [
"total",
"total_with_tax"
],
"description": "FuelTotals contains the summaries of all calculations for the fuel purchases."
}
},
"$comment": "Generated with GOBL v0.55.0"
}
60 changes: 60 additions & 0 deletions regimes/mx/fuel_complement.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package mx

import (
"github.com/invopop/gobl/cal"
"github.com/invopop/gobl/cbc"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/org"
"github.com/invopop/gobl/tax"
)

// FuelComplement carries the data to produce a CFDI's "Complemento de Estado de
// Cuenta de Combustibles para Monederos Electrónicos" (version 1.2 revision B)
// providing detailed information about fuel purchases made with electronic
// wallets. In Mexico, e-wallet suppliers are required to report this
// complementary information in the invoices they issue to their customers.
type FuelComplement struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So after reading the official name, had you considered any alternative names? Perhaps EWalletFuelComplement? I'm worried about potential colisions, and the fact that "FuelComplement" doesn't cover the wallet part...

Copy link
Contributor Author

@cavalle cavalle Sep 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering this name will also be part of the schema name, I tried to make it as short as possible. I suppose future name collisions are indeed a possibility (although probably small). In the XML, they call the root tag EstadoCuentaCombustibles, so they give more priority to the "estado de cuenta" part of the name than to the "e-wallet" aspect. So here's a list of options with their trade-offs:

Name Trade-offs
FuelComplement 👍 short and to the point
👎 not fully meaningful, collision-able
EWalletFuelComplement 👍 meaningful, no collisions
👎 long schema name
FuelAccountStatement 👍 direct translation of EstadoCuentaCombustibles
👎 no mention of e-wallet, no mention of being a complement

I don't love any of them, but I think all of them would work. Let me know if you have any preference (or any other suggestion) and we'll go with that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be inclined to go with the direct translation: FuelAccountStatement or FuelAccountBalance which is the translation I got from ChatGPT.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hehe, I got "Account Statement" from Deepl, but I like "Account Balance" better! (AIs FTW!)

// Customer's e-wallet account number.
WalletAccountNumber string `json:"wallet_account_number" jsonschema:"title=Wallet Account Number"`
// List of fuel purchases made with the customer's e-wallets.
Lines []*FuelLine `json:"lines" jsonschema:"title=Lines"`
// Summary of all the purchases totals, including taxes (calculated).
Totals *FuelTotals `json:"totals" jsonschema:"title=Totals" jsonschema_extras:"calculated=true"`
}

// FuelLine represents a single fuel purchase made with an e-wallet issued by
// the invoice's supplier.
type FuelLine struct {
// Identifier of the e-wallet used to make the purchase.
WalletID cbc.Code `json:"wallet_id" jsonschema:"title=Wallet Identifier"`
// Date and time of the purchase.
PurchaseDateTime cal.DateTime `json:"purchase_date_time" jsonschema:"title=Purchase Date and Time"`
// Tax ID (RFC) of the fuel seller.
SellerTaxID cbc.Code `json:"seller_tax_id" jsonschema:"title=Seller's Tax ID"`
// Code of the service station where the purchase was made.
ServiceStationCode cbc.Code `json:"service_station_code" jsonschema:"title=Service Station Code"`
// Amount of fuel units purchased
Quantity num.Amount `json:"quantity" jsonschema:"title=Quantity"`
// Reference unit of measure used in the price and the quantity.
Unit org.Unit `json:"unit" jsonschema:"title=Unit"`
// Type of fuel ("c_ClaveTipoCombustible" codes).
FuelType cbc.Code `json:"type,omitempty" jsonschema:"title=Type"`
// Name of the fuel
FuelName string `json:"name" jsonschema:"title=Name"`
// Base price of a single unit of the fuel.
Price num.Amount `json:"price" jsonschema:"title=Price"`
// Identifier of the purchase ("Folio").
PurchaseCode cbc.Code `json:"purchase_code" jsonschema:"title=Purchase Code"`
// Result of quantity multiplied by the item's price (calculated).
Total num.Amount `json:"total" jsonschema:"title=Total" jsonschema_extras:"calculated=true"`
// Map of taxes applied to the purchase.
Taxes tax.Set `json:"taxes" jsonschema:"title=Taxes"`
}

// FuelTotals contains the summaries of all calculations for the fuel purchases.
type FuelTotals struct {
// Sum of all line sums.
Total num.Amount `json:"total" jsonschema:"title=Total"`
// Grand total after taxes have been applied.
TotalWithTax num.Amount `json:"total_with_tax" jsonschema:"title=Total with Tax"`
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth adding any extra validation? Even if just the basics of ensuring that each field is a valid value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing! I just wanted us to focus on the data structure of the GOBL complement. But yes, I'm planning to add validations and calculations also. I think we're reaching a point where the structure is generally agreed on. I'll start pushing other changes soon.

4 changes: 4 additions & 0 deletions regimes/mx/mx.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import (
"github.com/invopop/gobl/l10n"
"github.com/invopop/gobl/org"
"github.com/invopop/gobl/regimes/common"
"github.com/invopop/gobl/schema"
"github.com/invopop/gobl/tax"
)

func init() {
tax.RegisterRegime(New())

// MX GOBL Schema Complements
schema.Register(schema.GOBL.Add("regimes/mx"), FuelComplement{})
}

// Custom keys used typically in meta or codes information.
Expand Down
Loading