import docx
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
from docx.oxml import OxmlElement, parse_xml
from docx.oxml.ns import nsdecls, qn

def create_boleta_doc():
    doc = docx.Document()
    
    # Configuración de márgenes
    sections = doc.sections
    for section in sections:
        section.top_margin = Inches(0.5)
        section.bottom_margin = Inches(0.5)
        section.left_margin = Inches(0.5)
        section.right_margin = Inches(0.5)
        
    # Estilo general
    style = doc.styles['Normal']
    font = style.font
    font.name = 'Arial'
    font.size = Pt(9)
    font.color.rgb = RGBColor(0x33, 0x33, 0x33)

    # Funciones de apoyo para celdas y bordes
    def set_cell_background(cell, hex_color):
        shading_elm = parse_xml(f'<w:shd {nsdecls("w")} w:fill="{hex_color}"/>')
        cell._tc.get_or_add_tcPr().append(shading_elm)

    def set_cell_margins(cell, top=60, bottom=60, left=100, right=100):
        tcPr = cell._tc.get_or_add_tcPr()
        tcMar = OxmlElement('w:tcMar')
        for m, val in [('top', top), ('bottom', bottom), ('left', left), ('right', right)]:
            node = OxmlElement(f'w:{m}')
            node.set(qn('w:w'), str(val))
            node.set(qn('w:type'), 'dxa')
            tcMar.append(node)
        tcPr.append(tcMar)

    def set_table_borders(table, color="D3D3D3", sz="4", val="single"):
        tblPr = table._tbl.tblPr
        borders = parse_xml(
            f'<w:tblBorders {nsdecls("w")}>\n'
            f'  <w:top w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
            f'  <w:left w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
            f'  <w:bottom w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
            f'  <w:right w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
            f'  <w:insideH w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
            f'  <w:insideV w:val="{val}" w:sz="{sz}" w:space="0" w:color="{color}"/>\n'
            f'</w:tblBorders>'
        )
        tblPr.append(borders)

    # Encabezado (Título y Datos de Empresa)
    t_head = doc.add_table(rows=1, cols=2)
    t_head.alignment = WD_TABLE_ALIGNMENT.CENTER
    t_head.autofit = False
    
    cell_left = t_head.rows[0].cells[0]
    cell_right = t_head.rows[0].cells[1]
    cell_left.width = Inches(3.8)
    cell_right.width = Inches(3.4)

    p1 = cell_left.paragraphs[0]
    r1 = p1.add_run("Boleta de Pago\n")
    r1.bold = True
    r1.font.size = Pt(18)
    r1.font.color.rgb = RGBColor(0x1B, 0x2A, 0x4A)

    r2 = p1.add_run("Mes: septiembre de 2026")
    r2.bold = True
    r2.font.size = Pt(11)

    p_info = cell_left.add_paragraph()
    p_info.paragraph_format.space_before = Pt(10)
    p_info.add_run("VÍCTOR RAUL CARBAJAL INCA\n").bold = True
    p_info.add_run("DNI: 43453964\n")
    p_info.add_run("Fecha de Ingreso: 2 de agosto de 2021\n")
    p_info.add_run("Cargo: Supervisor Técnico")

    # Bloque Empresa
    set_cell_background(cell_right, "BDD7EE")
    p_emp_title = cell_right.paragraphs[0]
    r_emp = p_emp_title.add_run("INFORMACIÓN EMPRESA\n")
    r_emp.bold = True
    r_emp.font.color.rgb = RGBColor(0x1B, 0x2A, 0x4A)

    p_emp_body = cell_right.add_paragraph()
    p_emp_body.add_run("RUC: 20604354219\n")
    p_emp_body.add_run("Razón Social: NETAXION PERU S.A.C.")

    doc.add_paragraph() # Espaciador

    # Tabla 1: Datos Laborales
    t1_data = [
        ["Tipo de Trabajador", "Regimen Pensionario", "CUSPP", "Situacion"],
        ["Empleado", "Habitat PE", "614271VCIBA4", "Vigente"],
        ["Días Laborados", "Días Subsidiados", "Días No Laborados", "Horas Trabajadas"],
        ["30.00", "0", "0", "198.00"],
        ["Sueldo Contractual", "Comprobantes de Vacaciones", "", ""],
        ["4,350.00", "", "", ""]
    ]

    t1 = doc.add_table(rows=len(t1_data), cols=4)
    t1.alignment = WD_TABLE_ALIGNMENT.CENTER
    set_table_borders(t1)

    for i, row_data in enumerate(t1_data):
        row = t1.rows[i]
        is_header = (i % 2 == 0)
        for j, val in enumerate(row_data):
            cell = row.cells[j]
            cell.text = val
            set_cell_margins(cell, 80, 80, 100, 100)
            p = cell.paragraphs[0]
            p.alignment = WD_ALIGN_PARAGRAPH.CENTER
            if is_header:
                set_cell_background(cell, "F2F2F2")
                p.runs[0].font.bold = True
                p.runs[0].font.size = Pt(8.5)

    doc.add_paragraph()

    # Tabla 2: Remuneraciones y Descuentos
    t2_headers = ["Detalle Remuneracion", "Haberes", "Descuentos"]
    t2_rows = [
        ("Haberes", "", ""),
        ("  Básico", "S/ 4,350.00", ""),
        ("  Horas Extras 100% ( 4.0 Horas )", "S/ 148.77", ""),
        ("  Asignación Familiar", "S/ 113.00", ""),
        ("  Viáticos", "S/ 260.00", ""),
        ("Descuentos Legales", "", ""),
        ("  SPP - Aportación Obligatoria", "", "S/ 461.18"),
        ("  SPP - Prima De Seguro", "", "S/ 63.18"),
        ("  Retención Impuesto mensual", "", "S/ 249.07"),
        ("Totales:", "S/ 4,871.77", "S/ 773.43"),
        ("NETO A PAGO:", "", "S/ 4,098.34")
    ]

    t2 = doc.add_table(rows=len(t2_rows) + 1, cols=3)
    t2.alignment = WD_TABLE_ALIGNMENT.CENTER
    set_table_borders(t2)

    # Cabecera T2
    hdr_cells = t2.rows[0].cells
    for j, name in enumerate(t2_headers):
        hdr_cells[j].text = name
        set_cell_background(hdr_cells[j], "D9D9D9")
        set_cell_margins(hdr_cells[j], 100, 100, 100, 100)
        p = hdr_cells[j].paragraphs[0]
        p.runs[0].font.bold = True
        if j > 0:
            p.alignment = WD_ALIGN_PARAGRAPH.RIGHT

    # Cuerpo T2
    for i, (col1, col2, col3) in enumerate(t2_rows):
        row_cells = t2.rows[i+1].cells
        row_cells[0].text = col1
        row_cells[1].text = col2
        row_cells[2].text = col3
        
        for j, cell in enumerate(row_cells):
            set_cell_margins(cell, 60, 60, 100, 100)
            p = cell.paragraphs[0]
            if j > 0:
                p.alignment = WD_ALIGN_PARAGRAPH.RIGHT

        # Formato de secciones especiales
        if col1 in ["Haberes", "Descuentos Legales", "Totales:", "NETO A PAGO:"]:
            for cell in row_cells:
                if p.runs:
                    p.runs[0].font.bold = True
            if col1 == "NETO A PAGO:":
                set_cell_background(row_cells[0], "F2F2F2")
                set_cell_background(row_cells[1], "F2F2F2")
                set_cell_background(row_cells[2], "F2F2F2")

    doc.save("Boleta_Pago_Sep2026.docx")

create_boleta_doc()

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: