@@ -171,19 +171,56 @@ def _build_invoice_data_annotations(invoice_data: ElementTree.Element, invoice:
171171 p_pmn .text = "1"
172172
173173
174+ def _build_tax_summary (parent : ElementTree .Element , invoice : Invoice ) -> None :
175+ """Emit P_13_*/P_14_* tax summary fields. Must be called before P_15."""
176+ ts = invoice .invoice_data .tax_summary
177+ if ts is None :
178+ return
179+
180+ paired_fields = [
181+ (ts .net_standard , "P_13_1" , ts .vat_standard , "P_14_1" , ts .vat_standard_pln , "P_14_1W" ),
182+ (ts .net_reduced_1 , "P_13_2" , ts .vat_reduced_1 , "P_14_2" , ts .vat_reduced_1_pln , "P_14_2W" ),
183+ (ts .net_reduced_2 , "P_13_3" , ts .vat_reduced_2 , "P_14_3" , ts .vat_reduced_2_pln , "P_14_3W" ),
184+ (ts .net_flat_rate , "P_13_4" , ts .vat_flat_rate , "P_14_4" , None , None ),
185+ (ts .net_oss , "P_13_5" , ts .vat_oss , "P_14_5" , None , None ),
186+ ]
187+ for net_val , net_tag , vat_val , vat_tag , vat_pln_val , vat_pln_tag in paired_fields :
188+ if net_val is not None :
189+ ElementTree .SubElement (parent , net_tag ).text = str (net_val )
190+ if vat_val is not None :
191+ ElementTree .SubElement (parent , vat_tag ).text = str (vat_val )
192+ if vat_pln_val is not None and vat_pln_tag is not None :
193+ ElementTree .SubElement (parent , vat_pln_tag ).text = str (vat_pln_val )
194+
195+ net_only_fields = [
196+ (ts .net_zero_domestic , "P_13_6_1" ),
197+ (ts .net_zero_wdt , "P_13_6_2" ),
198+ (ts .net_zero_export , "P_13_6_3" ),
199+ (ts .net_exempt , "P_13_7" ),
200+ (ts .net_not_subject , "P_13_8" ),
201+ (ts .net_not_subject_art100 , "P_13_9" ),
202+ (ts .net_reverse_charge , "P_13_10" ),
203+ ]
204+ for val , tag in net_only_fields :
205+ if val is not None :
206+ ElementTree .SubElement (parent , tag ).text = str (val )
207+
208+
174209def _build_invoice_data (root : ElementTree .Element , invoice : Invoice ) -> None :
175210 invoice_data = ElementTree .SubElement (root , "Fa" )
176- invoice_data_currency_code = ElementTree .SubElement (invoice_data , "KodWaluty" )
177- invoice_data_issue_date = ElementTree .SubElement (invoice_data , "P_1" )
178- invoice_data_invoice_number = ElementTree .SubElement (invoice_data , "P_2" )
179- invoice_data_sell_date = ElementTree .SubElement (invoice_data , "P_6" )
180- invoice_data_total_amount = ElementTree .SubElement (invoice_data , "P_15" )
181-
182- invoice_data_currency_code .text = invoice .invoice_data .currency_code
183- invoice_data_issue_date .text = invoice .invoice_data .issue_date .strftime ("%Y-%m-%d" )
184- invoice_data_invoice_number .text = invoice .invoice_data .issue_number
185- invoice_data_sell_date .text = invoice .invoice_data .sell_date .strftime ("%Y-%m-%d" )
186- invoice_data_total_amount .text = str (invoice .invoice_data .total_amount )
211+
212+ ElementTree .SubElement (invoice_data , "KodWaluty" ).text = invoice .invoice_data .currency_code
213+ ElementTree .SubElement (invoice_data , "P_1" ).text = invoice .invoice_data .issue_date .strftime (
214+ "%Y-%m-%d"
215+ )
216+ ElementTree .SubElement (invoice_data , "P_2" ).text = invoice .invoice_data .issue_number
217+ ElementTree .SubElement (invoice_data , "P_6" ).text = invoice .invoice_data .sell_date .strftime (
218+ "%Y-%m-%d"
219+ )
220+
221+ _build_tax_summary (invoice_data , invoice )
222+
223+ ElementTree .SubElement (invoice_data , "P_15" ).text = str (invoice .invoice_data .total_amount )
187224
188225 _build_invoice_data_annotations (invoice_data , invoice )
189226
@@ -193,18 +230,39 @@ def _build_invoice_data(root: ElementTree.Element, invoice: Invoice) -> None:
193230
194231 for index , row in enumerate (invoice .invoice_data .invoice_rows .rows , start = 1 ):
195232 invoice_data_row = ElementTree .SubElement (invoice_data , "FaWiersz" )
196- invoice_data_row_number = ElementTree .SubElement (invoice_data_row , "NrWierszaFa" )
197- invoice_data_row_name = ElementTree .SubElement (invoice_data_row , "P_7" )
198233
199- invoice_data_row_number .text = str (index )
200- invoice_data_row_name .text = row .name
234+ nr = ElementTree .SubElement (invoice_data_row , "NrWierszaFa" )
235+ nr .text = str (index )
236+
237+ if row .delivery_date is not None :
238+ p_6a = ElementTree .SubElement (invoice_data_row , "P_6A" )
239+ p_6a .text = row .delivery_date .strftime ("%Y-%m-%d" )
240+
241+ p_7 = ElementTree .SubElement (invoice_data_row , "P_7" )
242+ p_7 .text = row .name
243+
244+ if row .unit_of_measure is not None :
245+ p_8a = ElementTree .SubElement (invoice_data_row , "P_8A" )
246+ p_8a .text = row .unit_of_measure
247+
248+ if row .quantity is not None :
249+ p_8b = ElementTree .SubElement (invoice_data_row , "P_8B" )
250+ p_8b .text = str (row .quantity )
251+
252+ if row .unit_net_price is not None :
253+ p_9a = ElementTree .SubElement (invoice_data_row , "P_9A" )
254+ p_9a .text = str (row .unit_net_price )
255+
256+ if row .net_value is not None :
257+ p_11 = ElementTree .SubElement (invoice_data_row , "P_11" )
258+ p_11 .text = str (row .net_value )
201259
202260 if row .tax_oss is not None :
203- invoice_data_row_tax_oss = ElementTree .SubElement (invoice_data_row , "P_12_XII" )
204- invoice_data_row_tax_oss .text = str (row .tax_oss )
261+ p_12_xii = ElementTree .SubElement (invoice_data_row , "P_12_XII" )
262+ p_12_xii .text = str (row .tax_oss )
205263 elif row .tax is not None :
206- invoice_data_row_tax_rate = ElementTree .SubElement (invoice_data_row , "P_12" )
207- invoice_data_row_tax_rate .text = str (row .tax )
264+ p_12 = ElementTree .SubElement (invoice_data_row , "P_12" )
265+ p_12 .text = str (row .tax )
208266
209267
210268def convert_invoice_to_xml (invoice : Invoice , invoicing_software_name : str = "python-ksef" ) -> bytes :
0 commit comments