-
Notifications
You must be signed in to change notification settings - Fork 8
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
Food vouchers complement in MX #211
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
$schema: "https://gobl.org/draft-0/bill/invoice" | ||
issue_date: "2023-07-10" | ||
series: "TEST" | ||
code: "00002" | ||
supplier: | ||
name: "ESCUELA KEMPER URGATE" | ||
ext: | ||
mx-cfdi-fiscal-regime: "601" | ||
tax_id: | ||
country: "MX" | ||
code: "EKU9003173C9" | ||
zone: "21000" | ||
customer: | ||
name: "UNIVERSIDAD ROBOTICA ESPAÑOLA" | ||
ext: | ||
mx-cfdi-fiscal-regime: "601" | ||
mx-cfdi-use: "G01" | ||
tax_id: | ||
country: "MX" | ||
code: "URE180429TM6" | ||
zone: "86991" | ||
lines: | ||
- quantity: "1" | ||
item: | ||
name: "Comisión servicio de monedero electrónico" | ||
price: "10.00" | ||
ext: | ||
mx-cfdi-prod-serv: "84141602" | ||
taxes: | ||
- cat: "VAT" | ||
rate: "standard" | ||
payment: | ||
terms: | ||
notes: "Condiciones de pago" | ||
instructions: | ||
key: "online+wallet" | ||
complements: | ||
- $schema: "https://gobl.org/draft-0/regimes/mx/food-vouchers-complement" | ||
employer_registration: "12345678901234567890" | ||
account_number: "0123456789" | ||
lines: | ||
- e_wallet_id: "ABC1234" | ||
issue_date_time: "2022-07-19T10:20:30" | ||
employee: | ||
tax_code: "JUFA7608212V6" | ||
curp: "JUFA760821MDFRRR00" | ||
name: "Adriana Juarez Fernández" | ||
social_security: "12345678901" | ||
amount: 10.123 | ||
- e_wallet_id: "BCD4321" | ||
issue_date_time: "2022-08-20T11:20:30" | ||
employee: | ||
tax_code: "KAHO641101B39" | ||
curp: "KAHO641101HDFRRR00" | ||
name: "Oscar Kala Haak" | ||
amount: 20.4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
{ | ||
"$schema": "https://gobl.org/draft-0/envelope", | ||
"head": { | ||
"uuid": "8a51fd30-2a27-11ee-be56-0242ac120002", | ||
"dig": { | ||
"alg": "sha256", | ||
"val": "91514018429e4d46deb1f689658d361ae4870ac5e5aa76133018086fb923e31b" | ||
}, | ||
"draft": true | ||
}, | ||
"doc": { | ||
"$schema": "https://gobl.org/draft-0/bill/invoice", | ||
"type": "standard", | ||
"series": "TEST", | ||
"code": "00002", | ||
"issue_date": "2023-07-10", | ||
"currency": "MXN", | ||
"supplier": { | ||
"name": "ESCUELA KEMPER URGATE", | ||
"tax_id": { | ||
"country": "MX", | ||
"zone": "21000", | ||
"code": "EKU9003173C9" | ||
}, | ||
"ext": { | ||
"mx-cfdi-fiscal-regime": "601" | ||
} | ||
}, | ||
"customer": { | ||
"name": "UNIVERSIDAD ROBOTICA ESPAÑOLA", | ||
"tax_id": { | ||
"country": "MX", | ||
"zone": "86991", | ||
"code": "URE180429TM6" | ||
}, | ||
"ext": { | ||
"mx-cfdi-fiscal-regime": "601", | ||
"mx-cfdi-use": "G01" | ||
} | ||
}, | ||
"lines": [ | ||
{ | ||
"i": 1, | ||
"quantity": "1", | ||
"item": { | ||
"name": "Comisión servicio de monedero electrónico", | ||
"price": "10.00", | ||
"ext": { | ||
"mx-cfdi-prod-serv": "84141602" | ||
} | ||
}, | ||
"sum": "10.00", | ||
"taxes": [ | ||
{ | ||
"cat": "VAT", | ||
"rate": "standard", | ||
"percent": "16.0%" | ||
} | ||
], | ||
"total": "10.00" | ||
} | ||
], | ||
"payment": { | ||
"terms": { | ||
"notes": "Condiciones de pago" | ||
}, | ||
"instructions": { | ||
"key": "online+wallet" | ||
} | ||
}, | ||
"totals": { | ||
"sum": "10.00", | ||
"total": "10.00", | ||
"taxes": { | ||
"categories": [ | ||
{ | ||
"code": "VAT", | ||
"rates": [ | ||
{ | ||
"key": "standard", | ||
"base": "10.00", | ||
"percent": "16.0%", | ||
"amount": "1.60" | ||
} | ||
], | ||
"amount": "1.60" | ||
} | ||
], | ||
"sum": "1.60" | ||
}, | ||
"tax": "1.60", | ||
"total_with_tax": "11.60", | ||
"payable": "11.60" | ||
}, | ||
"complements": [ | ||
{ | ||
"$schema": "https://gobl.org/draft-0/regimes/mx/food-vouchers-complement", | ||
"employer_registration": "12345678901234567890", | ||
"account_number": "0123456789", | ||
"total": "30.52", | ||
"lines": [ | ||
{ | ||
"e_wallet_id": "ABC1234", | ||
"issue_date_time": "2022-07-19T10:20:30", | ||
"employee": { | ||
"tax_code": "JUFA7608212V6", | ||
"curp": "JUFA760821MDFRRR00", | ||
"name": "Adriana Juarez Fernández", | ||
"social_security": "12345678901" | ||
}, | ||
"amount": "10.12" | ||
}, | ||
{ | ||
"e_wallet_id": "BCD4321", | ||
"issue_date_time": "2022-08-20T11:20:30", | ||
"employee": { | ||
"tax_code": "KAHO641101B39", | ||
"curp": "KAHO641101HDFRRR00", | ||
"name": "Oscar Kala Haak" | ||
}, | ||
"amount": "20.40" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package mx | ||
|
||
import ( | ||
"regexp" | ||
|
||
"github.com/invopop/gobl/cal" | ||
"github.com/invopop/gobl/cbc" | ||
"github.com/invopop/gobl/num" | ||
"github.com/invopop/validation" | ||
) | ||
|
||
// Constants for the precision of the complement's amounts | ||
const ( | ||
FoodVouchersFinalPrecision = 2 | ||
) | ||
|
||
// Complement's Codes Patterns | ||
const ( | ||
CURPPattern = "^[A-Z][A,E,I,O,U,X][A-Z]{2}[0-9]{2}[0-1][0-9][0-3][0-9][M,H][A-Z]{2}[B,C,D,F,G,H,J,K,L,M,N,Ñ,P,Q,R,S,T,V,W,X,Y,Z]{3}[0-9,A-Z][0-9]$" | ||
SocialSecurityPattern = "^[0-9]{11}$" | ||
) | ||
|
||
// Complement's Codes Regexps | ||
var ( | ||
CURPRegexp = regexp.MustCompile(CURPPattern) | ||
SocialSecurityRegexp = regexp.MustCompile(SocialSecurityPattern) | ||
) | ||
|
||
// FoodVouchersComplement carries the data to produce a CFDI's "Complemento de | ||
// Vales de Despensa" (version 1.0) providing detailed information about food | ||
// vouchers issued by an e-wallet supplier to its customer's employees. | ||
// | ||
// This struct maps to the `ValesDeDespensa` root node in the CFDI's complement. | ||
type FoodVouchersComplement struct { | ||
// Customer's employer registration number (maps to `registroPatronal`). | ||
EmployerRegistration string `json:"employer_registration,omitempty" jsonschema:"title=Employer Registration"` | ||
// Customer's account number (maps to `numeroDeCuenta`). | ||
AccountNumber string `json:"account_number" jsonschema:"title=Account Number"` | ||
// Sum of all line amounts (calculated, maps to `total`). | ||
Total num.Amount `json:"total" jsonschema:"title=Total" jsonschema_extras:"calculated=true"` | ||
// List of food vouchers issued to the customer's employees (maps to `Conceptos`). | ||
Lines []*FoodVouchersLine `json:"lines" jsonschema:"title=Lines"` | ||
} | ||
|
||
// FoodVouchersLine represents a single food voucher issued to the e-wallet of | ||
// one of the customer's employees. It maps to one `Concepto` node in the CFDI's | ||
// complement. | ||
type FoodVouchersLine struct { | ||
// Identifier of the e-wallet that received the food voucher (maps to `Identificador`). | ||
EWalletID cbc.Code `json:"e_wallet_id" jsonschema:"title=E-wallet Identifier"` | ||
// Date and time of the food voucher's issue (maps to `Fecha`). | ||
IssueDateTime cal.DateTime `json:"issue_date_time" jsonschema:"title=Issue Date and Time"` | ||
// Employee that received the food voucher. | ||
Employee *FoodVouchersEmployee `json:"employee,omitempty" jsonschema:"title=Employee"` | ||
// Amount of the food voucher (maps to `importe`). | ||
Amount num.Amount `json:"amount" jsonschema:"title=Amount"` | ||
} | ||
|
||
// FoodVouchersEmployee represents an employee that received a food voucher. It | ||
// groups employee related field that appears under the `Concepto` node in the | ||
// CFDI's complement. | ||
type FoodVouchersEmployee struct { | ||
// Employee's tax identity code (maps to `rfc`). | ||
TaxCode cbc.Code `json:"tax_code" jsonschema:"title=Employee's Tax Identity Code"` | ||
// Employee's CURP ("Clave Única de Registro de Población", maps to `curp`). | ||
CURP cbc.Code `json:"curp" jsonschema:"title=Employee's CURP"` | ||
// Employee's name (maps to `nombre`). | ||
Name string `json:"name" jsonschema:"title=Employee's Name"` | ||
// Employee's Social Security Number (maps to `numSeguridadSocial`). | ||
SocialSecurity cbc.Code `json:"social_security,omitempty" jsonschema:"title=Employee's Social Security Number"` | ||
} | ||
|
||
// Validate checks the FoodVouchersComplement data according to the SAT's | ||
// rules for the "Complemento de Vales de Despensa". | ||
func (fvc *FoodVouchersComplement) Validate() error { | ||
return validation.ValidateStruct(fvc, | ||
validation.Field(&fvc.EmployerRegistration, validation.Length(0, 20)), | ||
validation.Field(&fvc.AccountNumber, | ||
validation.Required, | ||
validation.Length(0, 20), | ||
), | ||
validation.Field(&fvc.Total, validation.Required), | ||
validation.Field(&fvc.Lines, validation.Required), | ||
) | ||
} | ||
|
||
// Validate checks the FoodVouchersLine data is valid. | ||
func (fvl *FoodVouchersLine) Validate() error { | ||
return validation.ValidateStruct(fvl, | ||
validation.Field(&fvl.EWalletID, | ||
validation.Required, | ||
validation.Length(0, 20), | ||
), | ||
validation.Field(&fvl.IssueDateTime, cal.DateTimeNotZero()), | ||
validation.Field(&fvl.Employee, validation.Required), | ||
validation.Field(&fvl.Amount, validation.Required), | ||
) | ||
} | ||
|
||
// Validate checks the FoodVouchersEmployee data is valid. | ||
func (fve *FoodVouchersEmployee) Validate() error { | ||
return validation.ValidateStruct(fve, | ||
validation.Field(&fve.TaxCode, | ||
validation.Required, | ||
validation.By(validateTaxCode), | ||
), | ||
validation.Field(&fve.CURP, | ||
validation.Required, | ||
validation.Match(CURPRegexp), | ||
), | ||
validation.Field(&fve.Name, | ||
validation.Required, | ||
validation.Length(0, 100), | ||
), | ||
validation.Field(&fve.SocialSecurity, | ||
validation.Match(SocialSecurityRegexp), | ||
), | ||
) | ||
} | ||
|
||
// Calculate performs the complement's calculations and normalisations. | ||
func (fvc *FoodVouchersComplement) Calculate() error { | ||
fvc.Total = num.MakeAmount(0, FoodVouchersFinalPrecision) | ||
|
||
for _, l := range fvc.Lines { | ||
l.Amount = l.Amount.Rescale(FoodVouchersFinalPrecision) | ||
|
||
fvc.Total = fvc.Total.Add(l.Amount) | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great now 👍