Example #1
0
def gen_verification_sections(invoice, target_folder, serialno):
    """
    Generates the Customs Sections Verification document.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file tuple (path, type)

    .. rubric:: Template Used

    ``tendril/dox/templates/customs/verification-sections.tex``
    (:download:`Included version
    <../../tendril/dox/templates/customs/verification-sections.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at,
            from :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`.
        * - ``lines``
          - A list of :class:`tendril.sourcing.customs.CustomsInvoiceLine`
            instances.
        * - ``sno``
          - The serial number of the document.

    """
    outpath = os.path.join(
        target_folder,
        "customs-verification-sections-" + str(invoice.inv_no) + ".pdf"
    )
    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': invoice.given_data,
             'lines': invoice.lines,
             'sno': serialno + '.6',
             }

    outpath = render.render_pdf(stage,
                                'customs/verification-sections.tex',
                                outpath)
    return outpath, 'CUST-VERIF-SEC'
Example #2
0
def gen_verification_sections(invoice, target_folder, serialno):
    """
    Generates the Customs Sections Verification document.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file tuple (path, type)

    .. rubric:: Template Used

    ``tendril/dox/templates/customs/verification-sections.tex``
    (:download:`Included version
    <../../tendril/dox/templates/customs/verification-sections.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at,
            from :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`.
        * - ``lines``
          - A list of :class:`tendril.sourcing.customs.CustomsInvoiceLine`
            instances.
        * - ``sno``
          - The serial number of the document.

    """
    outpath = os.path.join(
        target_folder,
        "customs-verification-sections-" + str(invoice.inv_no) + ".pdf"
    )
    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': invoice.given_data,
             'lines': invoice.lines,
             'sno': serialno + '.6',
             }

    outpath = render.render_pdf(stage,
                                'customs/verification-sections.tex',
                                outpath)
    return outpath, 'CUST-VERIF-SEC'
Example #3
0
def render_po(stage, templateid, outpath):
    """
    Generates a purchase order using the template indicated by ``templateid``.

    :param stage: The dictionary to be sent along to the jinja2 template.
    :type stage: dict
    :param templateid: The id of the template to use.
    :type templateid: str
    :param outpath: The path to which the output should be written,
                    including ``.pdf``.
    :type outpath: str
    :return: The ``outpath``.

    .. rubric:: Template Used

    This function uses a template specified by ``templateid``, specifically,
    using the template named ``po_[templateid]_template.tex``.

    .. rubric:: Stage Keys Provided

    The contents of the ``stage`` provided to the jinja2 template are specific
    to each template, and it is the responsibility of the caller to make sure
    that it contains all the keys that the template expects. The parts of the
    stage defined by this function, common to all templates, are :

    .. list-table::

        * - ``no``
          - The serial number of the purchase order, either from the ``stage``
            parameter or created.
        * - ``point``
          - The name of the contact person, defined by
            :data:`tendril.utils.config.COMPANY_PO_POINT`.
        * - ``date``
          - The purchase order date, either from the ``stage`` parameter or
            today's date.
        * - ``lcofile``
          - The latex lcofile to use, defined by
            :data:`tendril.utils.config.COMPANY_PO_LCO_PATH`

    """
    template = 'po_' + templateid + '_template.tex'
    stage['lcofile'] = COMPANY_PO_LCO_PATH
    if 'point' not in stage.keys():
        stage['point'] = COMPANY_PO_POINT
    if 'no' not in stage.keys():
        stage['no'] = serialnos.get_serialno(series='PO', efield=templateid)
    if 'date' not in stage.keys():
        stage['date'] = str(datetime.date.today())
    return render.render_pdf(stage, template, outpath)
Example #4
0
def render_test_report_standalone(serialno,
                                  devicetype,
                                  suites,
                                  outfolder=None):

    if serialno is None:
        raise TypeError("serialno cannot be None")

    if devicetype is None:
        raise TypeError("devicetype cannot be None")

    if suites is None:
        raise TypeError("suites cannot be None")

    if outfolder is None:
        outfolder = os.path.join(INSTANCE_ROOT, 'scratch', 'testing')

    template = os.path.join('testing', 'test_report_template.tex')
    outpath = os.path.join(outfolder, 'TEST-REPORT-' + serialno + '.pdf')

    projectfolder = projects.cards[devicetype]
    gcf = ConfigsFile(projectfolder)

    graphs = []
    instruments = {}
    for suite in suites:
        for test in suite._tests:
            graphs.extend(test.graphs)
            graphs.extend(test.histograms)
            if test._inststr is not None and \
                    test._inststr not in instruments.keys():
                instruments[test._inststr] = len(instruments.keys()) + 1

    stage = {
        'suites': [x.render_dox() for x in suites],
        'sno': serialno,
        'testdate': max([x.ts for x in suites]).format(),
        'devicetype': devicetype,
        'desc': gcf.description(devicetype),
        'svnrevision': vcs.get_path_revision(projectfolder),
        'svnrepo': vcs.get_path_repository(projectfolder),
        'graphs': graphs,
        'instruments': instruments
    }

    return render_pdf(stage, template, outpath)
Example #5
0
def render_test_report_standalone(serialno, devicetype, suites, outfolder=None):

    if serialno is None:
        raise TypeError("serialno cannot be None")

    if devicetype is None:
        raise TypeError("devicetype cannot be None")

    if suites is None:
        raise TypeError("suites cannot be None")

    if outfolder is None:
        outfolder = os.path.join(INSTANCE_ROOT, 'scratch', 'testing')

    template = os.path.join('testing', 'test_report_template.tex')
    outpath = os.path.join(outfolder,
                           'TEST-REPORT-' + serialno + '.pdf')

    projectfolder = projects.cards[devicetype]
    gcf = ConfigsFile(projectfolder)

    graphs = []
    instruments = {}
    for suite in suites:
        for test in suite._tests:
            graphs.extend(test.graphs)
            graphs.extend(test.histograms)
            if test._inststr is not None and \
                    test._inststr not in instruments.keys():
                instruments[test._inststr] = len(instruments.keys()) + 1

    stage = {'suites': [x.render_dox() for x in suites],
             'sno': serialno,
             'testdate': max([x.ts for x in suites]).format(),
             'devicetype': devicetype,
             'desc': gcf.description(devicetype),
             'svnrevision': vcs.get_path_revision(projectfolder),
             'svnrepo': vcs.get_path_repository(projectfolder),
             'graphs': graphs,
             'instruments': instruments
             }

    return render_pdf(stage, template, outpath)
Example #6
0
 def generate_pdf(self, targetfolder, force=True):
     labels = [label for label in self._labels]
     nl = len(labels)
     sheets, remain = divmod(nl, self.base.lpp)
     if nl == 0:
         return None
     if remain > self.base.lpp * 0.8 or force is True:
         stage = {'labels': labels}
         self._labels = []
         logger.info("Creating all labels for sheet : " + self._code)
     elif sheets > 0:
         stage = {'labels': labels[:self.base.lpp * sheets]}
         self._labels = labels[self.base.lpp * sheets:]
         logger.info("Holding back " + str(remain) +
                     " labels for sheet : " + self._code)
     else:
         logger.info("Not generating labels for sheet : " + self._code +
                     ' ' + str(remain))
         return None
     return render.render_pdf(
         stage, self._base.templatefile,
         os.path.join(targetfolder, 'labels-' + self.code + '.pdf'))
Example #7
0
 def generate_pdf(self, targetfolder, force=True):
     labels = [label for label in self._labels]
     nl = len(labels)
     sheets, remain = divmod(nl, self.base.lpp)
     if nl == 0:
         return None
     if remain > self.base.lpp * 0.8 or force is True:
         stage = {'labels': labels}
         self._labels = []
         logger.info("Creating all labels for sheet : " + self._code)
     elif sheets > 0:
         stage = {'labels': labels[:self.base.lpp * sheets]}
         self._labels = labels[self.base.lpp * sheets:]
         logger.info("Holding back " +
                     str(remain) + " labels for sheet : " + self._code)
     else:
         logger.info("Not generating labels for sheet : " + self._code +
                     ' ' + str(remain))
         return None
     return render.render_pdf(
         stage,
         self._base.templatefile,
         os.path.join(targetfolder, 'labels-' + self.code + '.pdf')
     )
Example #8
0
def gen_confdoc(projfolder, configname, force=False):
    """
    Generate a PDF documenting a single configuration of the project. The
    document should include a reasonably thorough representation of the
    contents of the configuration related sections of the
    `tendril.gedaif.conffile.ConfigsFile``.

    :param projfolder: The gEDA project folder
    :type projfolder: str
    :param configname: The configuration name for which the BOM should be
                       generated.
    :type configname: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/confdocs/<configname>-doc.pdf``
    * Source Files : The project's schematic folder.

    .. rubric:: Template Used

    ``tendril/dox/templates/projects/geda-conf-doc.tex``
    (:download:`Included version
    <../../tendril/dox/templates/projects/geda-conf-doc.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``configname``
          - The name of the configuration (a card or cable name).
        * - ``desc``
          - The description of the configuration.
        * - ``pcbname``
          - The name of the base PCB.
        * - ``obom``
          - An :mod:`tendril.boms.outputbase.OutputBom` instance

    """
    gpf = projfile.GedaProjectFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    docfolder = get_project_doc_folder(projfolder)
    outpath = path.join(docfolder, 'confdocs', configname + '-doc.pdf')
    outf_mtime = fsutils.get_file_mtime(outpath, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + outpath)
        return outpath

    logger.info('Regenerating ' + outpath + os.linesep + 'Last modified : ' +
                str(sch_mtime) + '; Last Created : ' + str(outf_mtime))
    bom = boms_electronics.import_pcb(projfolder)
    obom = bom.create_output_bom(configname)
    group_oboms = bom.get_group_boms(configname)
    stage = {
        'configname': obom.descriptor.configname,
        'pcbname': obom.descriptor.pcbname,
        'bom': bom,
        'obom': obom,
        'group_oboms': group_oboms
    }

    config = obom.descriptor.configurations.configuration(configname)
    stage['desc'] = config['desc']

    template = 'projects/geda-conf-doc.tex'

    workspace_outpath = workspace_fs.getsyspath(outpath)
    workspace_fs.makedir(path.dirname(outpath),
                         recursive=True,
                         allow_recreate=True)
    render.render_pdf(stage, template, workspace_outpath)
    copyfile(workspace_fs, outpath, refdoc_fs, outpath, overwrite=True)

    return outpath
Example #9
0
def gen_verification_checklist(invoice, target_folder, serialno):
    """
    Generates the Customs Duties / Checklist Verification document.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file tuple (path, type)

    .. rubric:: Template Used

    ``tendril/dox/templates/customs/verification-duties.tex``
    (:download:`Included version
    <../../tendril/dox/templates/customs/verification-duties.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at,
            from :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`.
        * - ``lines``
          - A list of :class:`tendril.sourcing.customs.CustomsInvoiceLine`
            instances.
        * - ``invoice``
          - The :class:`tendril.sourcing.customs.CustomsInvoice` instance.
        * - ``sno``
          - The serial number of the document.
        * - ``summary``
          - A list of dicts containing the summary of the customs duties
            applicable against a particular section, as described below

    .. list-table:: Summary keys

        * - ``section``
          - The HS section, a
            :class:`tendril.sourcing.customs.CustomsSection`` instance.
        * - ``code``
          - The HS section code.
        * - ``name``
          - The HS section name.
        * - ``idxs``
          - Line numbers classified into this line.
        * - ``qty``
          - Total quantity of all lines classified into this line.
        * - ``assessablevalue``
          - Total assessable value of all lines classified into this line.
        * - ``bcd``
          - Total Basic Customs Duty applicable against this section.
        * - ``cvd``
          - Total Countervailing Duty applicable against this section.
        * - ``acvd``
          - Total Additional Countervailing Duty applicable against
            this section.
        * - ``cec``
          - Total Education Cess on Customs Duty applicable against
            this section.
        * - ``cshec``
          - Total Secondary and Higher Education Cess on Customs Duty
            applicable against this section.
        * - ``cvdec``
          - Total Education Cess on Countervailing Duty applicable
            against this section.
        * - ``cvdshec``
          - Total Secondary and Higher Education Cess on Countervailing Duty
            applicable against this section.

    """
    print("Generating Customs Duty Verification Checklist")
    outpath = os.path.join(
        target_folder,
        "customs-verification-duties-" + str(invoice.inv_no) + ".pdf"
    )
    summary = []
    pb = TendrilProgressBar(max=len(invoice.hssections))
    print("Collating Section Summaries...")
    for section in invoice.hssections:
        secsum = {'section': section,
                  'code': section.code,
                  'name': section.name,
                  'idxs': invoice.getsection_idxs(hssection=section),
                  'assessablevalue':
                  invoice.getsection_assessabletotal(hssection=section),
                  'qty': invoice.getsection_qty(hssection=section),
                  'bcd':
                  sum([x.bcd.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'cvd':
                  sum([x.cvd.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'acvd':
                  sum([x.acvd.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'cec':
                  sum([x.cec.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'cshec':
                  sum([x.cshec.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'cvdec':
                  sum([x.cvdec.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'cvdshec':
                  sum([x.cvdshec.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  }
        summary.append(secsum)
        pb.next(note=section.code + ' ' + section.name)
    pb.finish()
    pb = TendrilProgressBar(max=len(invoice.lines))
    pb_summary = TendrilProgressBar(max=len(summary))
    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': invoice.given_data,
             'lines': invoice.lines,
             'summary': summary,
             'invoice': invoice,
             'sno': serialno + '.7',
             'pb': pb,
             'pb_summary': pb_summary}
    print("Rendering...")
    outpath = render.render_pdf(
        stage, 'customs/verification-duties.tex', outpath
    )
    return outpath, 'CUST-VERIF-BOE'
Example #10
0
def gen_declaration(invoice, target_folder, copyt, serialno):
    """
    Generates a copy of the Customs Declaration for Imports.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param copyt: A string specifying which copy it is ("ORIGINAL",
                  "DUPLICATE", so on)
    :type copyt: str
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file path

    .. rubric:: Template Used

    ``tendril/dox/templates/customs/decl.tex``
    (:download:`Included version
    <../../tendril/dox/templates/customs/decl.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at, from
            :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`
        * - ``currency``
          - The symbol of the currency of the invoice.
        * - ``inv_total``
          - The total value of the invoice, in vendor currency.
        * - ``exchrate``
          - The applicable exchange rate.
        * - ``exchnotif``
          - The government notification number specifying the exchange rate.
        * - ``exchnotifdt``
          - The date of the exchange rate notification.
        * - ``extended_total_sc``
          - The extended total invoice value, in the vendor's currency.
        * - ``assessable_total_sc``
          - The assessable total invoice value, in the vendor's currency.
        * - ``assessable_total_nc``
          - The assessable total invoice value, in the vendor's currency.
        * - ``copyt``
          - The string specifying which copy it is.
        * - ``sno``
          - The serial number of the document.

    """
    outpath = os.path.join(
        target_folder,
        "customs-declaration-" + copyt + '-' + str(invoice.inv_no) + ".pdf"
    )

    given_data = copy.deepcopy(invoice.given_data)

    for k, v in given_data['costs_not_included'].iteritems():
        given_data['costs_not_included'][k] = render.escape_latex(v)

    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': given_data,
             'currency': render.escape_latex(invoice.currency.symbol),
             'inv_total':
             render.escape_latex(invoice.extendedtotal.source_string),
             'exchrate': invoice.given_data['exchrate'],
             'exchnotif': invoice.given_data['exchnotif'],
             'exchnotifdt': invoice.given_data['exchnotif_date'],
             'extended_total_sc':
             render.escape_latex(invoice.extendedtotal.source_string),
             'assessable_total_sc':
             render.escape_latex(invoice.assessabletotal.source_string),
             'assessable_total_nc':
             render.escape_latex(invoice.assessabletotal.native_string),
             'copyt': copyt,
             'sno': serialno + '.5'
             }

    return render.render_pdf(stage, 'customs/decl.tex', outpath)
Example #11
0
def gen_tech_writeup(invoice, target_folder, serialno):
    """
    Generates the Customs Technical Writeup.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file path

    .. rubric:: Template Used

    Template Filename :
    ``tendril/dox/templates/customs/technical-writeup.tex``
    (:download:`Included version
    <../../tendril/dox/templates/customs/technical-writeup.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at,
            from :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`
        * - ``sno``
          - The serial number of the document.
        * - ``linecount``
          - The number of lines in the invoice.
        * - ``tqty``
          - The total quantity.
        * - ``tvalue``
          - The total value.
        * - ``unclassified``
          - Lines in the invoice which could not be classified
        * - ``sectable``
          - The secion table, containing a list of ``section lines``,
            described below. The 'sections' here are Customs HS Codes.

    .. list-table:: Section line keys

        * - ``code``
          - The HS section code.
        * - ``name``
          - The HS section name.
        * - ``idxs``
          - Line numbers classified into this line.
        * - ``qty``
          - Total quantity of all lines classified into this line.
        * - ``value``
          - Total value of all lines classified into this line.

    """
    outpath = os.path.join(
        target_folder,
        "customs-tech-writeup-" + str(invoice.inv_no) + ".pdf"
    )
    sectable = []
    tqty = 0
    tvalue = 0
    for section in invoice.hssections:
        lval = invoice.getsection_assessabletotal(section).source_string
        secline = {'code': section.code,
                   'name': section.name,
                   'idxs': invoice.getsection_idxs(section),
                   'qty': invoice.getsection_qty(section),
                   'value': render.escape_latex(lval)
                   }
        sectable.append(secline)
        tqty += invoice.getsection_qty(section)
        tvalue += invoice.getsection_assessabletotal(section)

    unclassified = {'idxs': [x.idx for x in invoice.unclassified],
                    'qty': sum([x.qty for x in invoice.unclassified]),
                    }
    if unclassified['qty'] > 0:
        unclassified['value'] = \
            render.escape_latex(
                sum([x.assessableprice
                     for x in invoice.unclassified]).source_string)
        tvalue += sum([x.assessableprice for x in invoice.unclassified])
        tqty += unclassified['qty']
    else:
        unclassified['value'] = None

    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': invoice.given_data,
             'linecount': invoice.linecount,
             'sectable': sectable,
             'tqty': tqty,
             'tvalue': render.escape_latex(tvalue.source_string),
             'unclassified': unclassified,
             'sno': serialno + '.4'
             }
    return render.render_pdf(stage, 'customs/technical-writeup.tex', outpath)
Example #12
0
def gen_production_order(outfolder, prod_sno, sourcedata, snos,
                         sourcing_orders=None, root_orders=None,
                         verbose=True):
    """
    Generates a Production Order for a production order defined in a
    ``.yaml`` file.

    .. note::
        This function does not register the document in the
        :mod:`tendril.dox.docstore`. You should use the output file path
        (returned by this function) to register the document when desired.

    .. todo:: Update this function to also handle registering once the main
              scripts are better integrated into the core.

    .. todo:: Document the format of the .yaml file.

    :param outfolder: The folder within which the output file
                      should be created.
    :type outfolder: str
    :param prod_sno: The serial number of the Production Order to generate.
    :type prod_sno: str
    :param sourcedata: The source data loaded from a ``.yaml`` file.
    :type sourcedata: dict
    :param snos: A list of serial numbers to produce, along with whatever
                 other information should be included in the order. See
                 the template for details.
    :type snos: :class:`list` of :class:`dict`
    :param sourcing_orders: A list of sourcing orders which were made to
                            obtain raw materials for this production order.
    :type sourcing_orders: :class:`list` of :class:`str`
    :param root_orders: A list of root orders which is production order is
                        intended to fulfill.
    :type root_orders: :class:`list` of :class:`str`
    :return: The path to the output PDF file.

    .. rubric:: Template Used

    ``tendril\dox\\templates\production\production-order-template.tex``
    (:download:`Included version
    <../../tendril/dox/templates/production/production-order-template.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``sno``
          - The serial number of the production order.
        * - ``title``
          - The title of the production order.
        * - ``cards``
          - A list of different card types to be produced,
            and quantities of each.
        * - ``snos``
          - A list of cards to produce, with serial numbers and other included
            information.
        * - ``sourcing_orders``
          - A list of sourcing orders which were made to obtain raw materials
            for this production order.
        * - ``root_orders``
          - A list of root orders which is production order is
            intended to fulfill.

    """

    cards = []
    if 'cards' in sourcedata.keys():
        cards = [{'qty': sourcedata['cards'][k],
                  'desc': ConfigsFile(projects.cards[k]).description(k),
                  'ident': k} for k in sorted(sourcedata['cards'].keys())]

    deltas = {}
    if 'deltas' in sourcedata.keys():
        for delta in sourcedata['deltas']:
            desc = delta['orig-cardname'] + ' -> ' + delta['target-cardname']
            if desc in deltas.keys():
                deltas[desc] += 1
            else:
                deltas[desc] = 1

    lroot_orders = []
    for root_order in root_orders:
        if root_order is not None:
            try:
                root_order_desc = serialnos.get_serialno_efield(root_order)
            except AttributeError:
                root_order_desc = None
        else:
            root_order_desc = None
        lroot_orders.append({'no': root_order, 'desc': root_order_desc})

    stage = {
        'title': sourcedata['title'],
        'cards': cards,
        'deltas': deltas,
        'sourcing_orders': sourcing_orders,
        'sno': prod_sno,
        'snos': snos,
        'root_orders': lroot_orders,
    }

    outpath = os.path.join(outfolder, str(prod_sno) + '.pdf')
    template = 'production/production-order-template.tex'
    render.render_pdf(stage, template, outpath, verbose=verbose)
    return outpath
Example #13
0
def render():
    t1 = time.time()
    lang = request.form['lang']
    source = request.form['source']
    mode = request.form['mode']
    fmt = request.form['format']
    background = str(request.form['background'])
    alpha = request.form.get('alpha','off') == "on"
    if request.form.get('restrictWidth', 'off') == "on":
        width = int(request.form['width'])
    else:
        width = None
    if request.form.get('restrictHeight', 'off') == "on":
        height = int(request.form['height'])
    else:
        height = None

    request_params = frozenset([lang, source, mode, fmt, background, alpha, time.time()])

    # Generate a correlation id for debugging
    app.extensions['correlation_id'] = hash(request_params)

    # Wrap the logger with some request context
    logger = logging.getLogger("source2Image")
    logger = logging.LoggerAdapter(logger, app.extensions)

    # Input validation
    assert fmt in formats
    assert lang in languages
    assert width <= 2048
    assert height <= 2048

    logger.info("Begin handle of request")

    wd = tempfile.mkdtemp()
    logger.info("Creating temp directory %s" % wd)

    # Sanitize the LaTeX source
    if '\end{lstlisting}' in source:
        source = source.replace('\end{lstlisting}', '%\\textbackslash)end{lstlisting}')

    latexTmpl = texenv.get_template("source-listing.tex")
    latexBody = latexTmpl.render(lang=lang, source=source)

    # Generate PDF
    pdfPath = render_pdf(latexBody, wd)
    if not pdfPath:
        abort(503)

    # Determine the correct output, convert with ImageMagick if necessary
    if fmt == "pdf":
        fileBytes = open(pdfPath, "r").read()
        contentType = "application/pdf"
        fileName = "%s-listing.pdf" % lang.lower()
    elif fmt == "png":
        outPath = convert(pdfPath, "texput.png", wd, 
                alpha=alpha, background=background, resize=(width, height))
        if not outPath:
            abort(503)
        else:
            fileBytes = open(outPath, "r").read()
            contentType = "image/png"
            fileName = "%s-listing.png" % lang.lower()
    elif fmt == "jpg":
        outPath = convert(pdfPath, "texput.jpg", wd,
                alpha=False, background=background, resize=(width, height))
        if not outPath:
            abort(503)
        else:
            fileBytes = open(outPath, "r").read()
            contentType = "image/jpeg"
            fileName = "%s-listing.jpg" % lang.lower()

    # Make the response
    resp = make_response(fileBytes)
    resp.headers["Content-Type"] = contentType

    if mode == "download":
        resp.headers["Content-Disposition"] = "attachment; filename=%s" % fileName

    logger.info("Removing %s" % wd)
    shutil.rmtree(wd)
    t2 = time.time()
    logger.info("End handle of request. Finished in %0.2fs" % (t2-t1))
    return resp
Example #14
0
def gen_authorization(invoice, target_folder, serialno):
    """
    Generates the Customs CHA Authorization Letter.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file path

    .. rubric:: Template Used

    This function uses a different template for each CHA, in the format
    that the CHA asks for it.

    Template Filename :
    ``tendril/dox/templates/customs/authorization.<cha>.tex``

    Included Templates :

    .. list-table::

        * - FedEx India
          - ``tendril/dox/templates/customs/authorization.fedex.tex``
          - (:download:`Included version <../../tendril/dox/templates/\
customs/authorization.fedex.tex>`)
        * - DHL India
          - ``tendril/dox/templates/customs/authorization.dhl.tex``
          - (:download:`Included version <../../tendril/dox/templates/\
customs/authorization.dhl.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at,
            from :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`
        * - ``sno``
          - The serial number of the document.

    """
    outpath = os.path.join(
        target_folder,
        "customs-authorization-" + str(invoice.inv_no) + ".pdf"
    )
    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': invoice.given_data,
             'sno': serialno + '.1'
             }

    if invoice.given_data['cha'] == 'DHL':
        template = 'customs/authorization.dhl.tex'
    elif invoice.given_data['cha'] == 'FedEx':
        template = 'customs/authorization.fedex.tex'
    else:
        raise ValueError('CHA unsupported')
    return render.render_pdf(stage, template, outpath)
Example #15
0
def gen_delta_pcb_am(orig_cardname, target_cardname, outfolder=None, sno=None,
                     productionorderno=None, indentsno=None, scaffold=False,
                     verbose=True, session=None):
    """
    Generates a Delta PCB Assembly Manifest for converting one card to
    another. This is typically only useful when the two cards are very
    closely related and use the same PCB..

    In the present implementation, the cardname could represent either a PCB
    or a Cable.

    .. note::
        This function does not register the document in the
        :mod:`tendril.dox.docstore`. You should use the output file path
        (returned by this function) to register the document when desired.

    .. seealso::
        - :mod:`tendril.entityhub.projects`, for information about 'cards'

    .. todo:: Update this function to also handle registering once the main
              scripts are better integrated into the core.

    :param orig_cardname: The name of the original card. This should be
                              present in :data:`entityhub.projects.cards`
    :type orig_cardname: str
    :param target_cardname: The name of the target card. This should be
                              present in :data:`entityhub.projects.cards`
    :type target_cardname: str
    :param outfolder: The folder within which the output file should be
                      created.
    :type outfolder: str
    :param sno: The serial number of the card for which you want the Delta
                Assembly Manifest.
    :type sno: str
    :param productionorderno: The serial number of the Production Order for
                              the modification.
    :type productionorderno: str
    :param indentsno: The serial number of the Stock Indent which accounts for
                      the components used in this card.
    :type indentsno: str
    :return: The path of the generated file.

    .. rubric:: Template Used

    ``tendril/dox/templates/production/delta-assem-manifest.tex``
    (:download:`Included version
    <../../tendril/dox/templates/production/delta-assem-manifest.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``sno``
          - The serial number of the card.
        * - ``orig_configname``
          - The configuration name of the original card.
        * - ``target_configname``
          - The configuration name of the target card.
        * - ``pcbname``
          - The name of the original PCB.
        * - ``title``
          - Whether the device is a PCB or a Cable.
        * - ``desc``
          - The description of the modification.
        * - ``addition_lines``
          - List of :class:`tendril.boms.outputbase.OutputBomLine` instances.
        * - ``subtraction_lines``
          - List of :class:`tendril.boms.outputbase.OutputBomLine` instances.
        * - ``stockindent``
          - The serial number of the Stock Indent which accounts for
            the components used in this card.
        * - ``productionorderno``
          - The serial number of the Production Order for the card.
        * - ``original_repopath``
          - The root of the VCS repository which contains the original gEDA project.
        * - ``target_repopath``
          - The root of the VCS repository which contains the target gEDA project.
        * - ``evenpages``
          - Whether to render PDF with even number of pages by adding an extra
            page if needed (useful for bulk printing).

    """

    if outfolder is None:
        from tendril.utils.config import INSTANCE_ROOT
        outfolder = os.path.join(INSTANCE_ROOT, 'scratch', 'production')

    if sno is None:
        # TODO Generate real S.No. here
        sno = 1

    outpath = os.path.join(
            outfolder,
            'dm-' + orig_cardname + '->' + target_cardname +
            '-' + str(sno) + '.pdf'
    )

    orig_instance = get_module_instance(sno, orig_cardname,
                                        session=session, scaffold=True)
    orig_obom = orig_instance.obom
    target_instance = get_module_prototype(target_cardname)
    target_obom = target_instance.obom

    delta_obom = DeltaOutputBom(orig_obom, target_obom)

    if projects.check_module_is_card(orig_cardname):
        orig_entityname = orig_instance.pcbname
        try:
            target_entityname = target_instance.pcbname
        except AttributeError:
            logger.error("Target for the delta should be a PCB!")
            raise
        title = 'PCB '
        evenpages = True
    elif projects.check_module_is_cable(orig_cardname):
        orig_entityname = orig_instance.cblname
        try:
            target_entityname = target_instance.cblname
        except AttributeError:
            logger.error("Target for the delta should be a Cable!")
            raise
        title = 'Cable '
        evenpages = False
    else:
        raise ValueError

    stage = {'orig_configname': orig_cardname,
             'target_configname': target_cardname,
             'pcbname': orig_entityname,
             'title': title,
             'sno': sno,
             'addition_lines': delta_obom.additions_bom.lines,
             'subtraction_lines': delta_obom.subtractions_bom.lines,
             'evenpages': evenpages,
             'stockindent': indentsno,
             'orig_repopath': projects.get_project_repo_repr(orig_cardname),
             'target_repopath': projects.get_project_repo_repr(target_cardname),  # noqa
             'productionorderno': productionorderno,
             'desc': delta_obom.descriptor.configname}

    template = 'production/delta-assem-manifest.tex'

    render.render_pdf(stage, template, outpath, verbose=verbose)
    return outpath
Example #16
0
def render_test_report(serialno=None, outfolder=None, session=None):
    """
    Renders the latest test results marked against the specified ``serialno``.

    Since this function is defined against the database, all arguments should
    be keyword arguments.

    :param serialno: The serial number of the device.
    :type serialno: :class:`str` or :class:`tendril.entityhub.db.SerialNumber`
    :param outfolder: The folder in which the output file should be created.
    :type outfolder: str
    :param session: The database session. If None, the function will make
                    it's own.
    :return: The output file path.

    .. rubric:: Template Used

    ``tendril/dox/templates/testing/test_report_template.tex``
    (:download:`Included version
    <../../tendril/dox/templates/testing/test_report_template.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``sno``
          - Serial number of the device.
        * - ``testdate``
          - The timestamp of the latest test suite.
        * - ``devicetype``
          - The device type.
        * - ``desc``
          - The device description.
        * - ``svnrevision``
          - The VCS revision of the project config file.
        * - ``svnrepo``
          - The VCS repository containing the project
        * - ``graphs``
          - A list of graphs, each graph being a list of tuples of
            (graphpath, graphtitle)
        * - ``instruments``
          - A list of instrument ident strings, one for each unique
            instrument used in the suites.
        * - ``suites``
          - A list of instances of
            :class:`tendril.testing.testbase.TestSuiteBase` or its subclasses.

    Note that the ``suites`` provided to the template are typically
    expected to be offline test suites which are reconstructed from the
    database.

    .. seealso:: :func:`tendril.testing.analysis.get_test_suite_objects`

    """
    if serialno is None:
        raise ValueError("serialno cannot be None")
    if not isinstance(serialno, SerialNumber):
        serialno = sno_controller.get_serialno_object(sno=serialno,
                                                      session=session)
    if outfolder is None:
        outfolder = os.path.join(INSTANCE_ROOT, 'scratch', 'testing')

    template = os.path.join('testing', 'test_report_template.tex')
    outpath = os.path.join(outfolder, 'TEST-REPORT-' + serialno.sno + '.pdf')

    devicetype = serialnos.get_serialno_efield(sno=serialno.sno,
                                               session=session)
    projectfolder = projects.cards[devicetype]
    gcf = ConfigsFile(projectfolder)

    suites = analysis.get_test_suite_objects(serialno=serialno.sno,
                                             session=session)
    graphs = []
    instruments = {}
    for suite in suites:
        for test in suite._tests:
            graphs.extend(test.graphs)
            graphs.extend(test.histograms)
            if test._inststr is not None and \
                    test._inststr not in instruments.keys():
                instruments[test._inststr] = len(instruments.keys()) + 1

    stage = {
        'suites': [x.render_dox() for x in suites],
        'sno': serialno.sno,
        'testdate': max([x.ts for x in suites]).format(),
        'devicetype': devicetype,
        'desc': gcf.description(devicetype),
        'svnrevision': vcs.get_path_revision(projectfolder),
        'svnrepo': vcs.get_path_repository(projectfolder),
        'graphs': graphs,
        'instruments': instruments
    }

    return render_pdf(stage, template, outpath)
Example #17
0
def gen_tech_writeup(invoice, target_folder, serialno):
    """
    Generates the Customs Technical Writeup.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file path

    .. rubric:: Template Used

    Template Filename :
    ``tendril/dox/templates/customs/technical-writeup.tex``
    (:download:`Included version
    <../../tendril/dox/templates/customs/technical-writeup.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at,
            from :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`
        * - ``sno``
          - The serial number of the document.
        * - ``linecount``
          - The number of lines in the invoice.
        * - ``tqty``
          - The total quantity.
        * - ``tvalue``
          - The total value.
        * - ``unclassified``
          - Lines in the invoice which could not be classified
        * - ``sectable``
          - The secion table, containing a list of ``section lines``,
            described below. The 'sections' here are Customs HS Codes.

    .. list-table:: Section line keys

        * - ``code``
          - The HS section code.
        * - ``name``
          - The HS section name.
        * - ``idxs``
          - Line numbers classified into this line.
        * - ``qty``
          - Total quantity of all lines classified into this line.
        * - ``value``
          - Total value of all lines classified into this line.

    """
    outpath = os.path.join(
        target_folder,
        "customs-tech-writeup-" + str(invoice.inv_no) + ".pdf"
    )
    sectable = []
    tqty = 0
    tvalue = 0
    for section in invoice.hssections:
        lval = invoice.getsection_assessabletotal(section).source_string
        secline = {'code': section.code,
                   'name': section.name,
                   'idxs': invoice.getsection_idxs(section),
                   'qty': invoice.getsection_qty(section),
                   'value': render.escape_latex(lval)
                   }
        sectable.append(secline)
        tqty += invoice.getsection_qty(section)
        tvalue += invoice.getsection_assessabletotal(section)

    unclassified = {'idxs': [x.idx for x in invoice.unclassified],
                    'qty': sum([x.qty for x in invoice.unclassified]),
                    }
    if unclassified['qty'] > 0:
        unclassified['value'] = \
            render.escape_latex(
                sum([x.assessableprice
                     for x in invoice.unclassified]).source_string)
        tvalue += sum([x.assessableprice for x in invoice.unclassified])
        tqty += unclassified['qty']
    else:
        unclassified['value'] = None

    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': invoice.given_data,
             'linecount': invoice.linecount,
             'sectable': sectable,
             'tqty': tqty,
             'tvalue': render.escape_latex(tvalue.source_string),
             'unclassified': unclassified,
             'sno': serialno + '.4'
             }
    return render.render_pdf(stage, 'customs/technical-writeup.tex', outpath)
Example #18
0
def gen_production_order(outfolder,
                         prod_sno,
                         sourcedata,
                         snos,
                         sourcing_orders=None,
                         root_orders=None,
                         verbose=True):
    """
    Generates a Production Order for a production order defined in a
    ``.yaml`` file.

    .. note::
        This function does not register the document in the
        :mod:`tendril.dox.docstore`. You should use the output file path
        (returned by this function) to register the document when desired.

    .. todo:: Update this function to also handle registering once the main
              scripts are better integrated into the core.

    .. todo:: Document the format of the .yaml file.

    :param outfolder: The folder within which the output file
                      should be created.
    :type outfolder: str
    :param prod_sno: The serial number of the Production Order to generate.
    :type prod_sno: str
    :param sourcedata: The source data loaded from a ``.yaml`` file.
    :type sourcedata: dict
    :param snos: A list of serial numbers to produce, along with whatever
                 other information should be included in the order. See
                 the template for details.
    :type snos: :class:`list` of :class:`dict`
    :param sourcing_orders: A list of sourcing orders which were made to
                            obtain raw materials for this production order.
    :type sourcing_orders: :class:`list` of :class:`str`
    :param root_orders: A list of root orders which is production order is
                        intended to fulfill.
    :type root_orders: :class:`list` of :class:`str`
    :return: The path to the output PDF file.

    .. rubric:: Template Used

    ``tendril\dox\\templates\production\production-order-template.tex``
    (:download:`Included version
    <../../tendril/dox/templates/production/production-order-template.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``sno``
          - The serial number of the production order.
        * - ``title``
          - The title of the production order.
        * - ``cards``
          - A list of different card types to be produced,
            and quantities of each.
        * - ``snos``
          - A list of cards to produce, with serial numbers and other included
            information.
        * - ``sourcing_orders``
          - A list of sourcing orders which were made to obtain raw materials
            for this production order.
        * - ``root_orders``
          - A list of root orders which is production order is
            intended to fulfill.

    """

    cards = []
    if 'cards' in sourcedata.keys():
        cards = [{
            'qty': sourcedata['cards'][k],
            'desc': ConfigsFile(projects.cards[k]).description(k),
            'ident': k
        } for k in sorted(sourcedata['cards'].keys())]

    deltas = {}
    if 'deltas' in sourcedata.keys():
        for delta in sourcedata['deltas']:
            desc = delta['orig-cardname'] + ' -> ' + delta['target-cardname']
            if desc in deltas.keys():
                deltas[desc] += 1
            else:
                deltas[desc] = 1

    lroot_orders = []
    for root_order in root_orders:
        if root_order is not None:
            try:
                root_order_desc = serialnos.get_serialno_efield(root_order)
            except AttributeError:
                root_order_desc = None
        else:
            root_order_desc = None
        lroot_orders.append({'no': root_order, 'desc': root_order_desc})

    stage = {
        'title': sourcedata['title'],
        'cards': cards,
        'deltas': deltas,
        'sourcing_orders': sourcing_orders,
        'sno': prod_sno,
        'snos': snos,
        'root_orders': lroot_orders,
    }

    outpath = os.path.join(outfolder, str(prod_sno) + '.pdf')
    template = 'production/production-order-template.tex'
    render.render_pdf(stage, template, outpath, verbose=verbose)
    return outpath
Example #19
0
def gen_authorization(invoice, target_folder, serialno):
    """
    Generates the Customs CHA Authorization Letter.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file path

    .. rubric:: Template Used

    This function uses a different template for each CHA, in the format
    that the CHA asks for it.

    Template Filename :
    ``tendril/dox/templates/customs/authorization.<cha>.tex``

    Included Templates :

    .. list-table::

        * - FedEx India
          - ``tendril/dox/templates/customs/authorization.fedex.tex``
          - (:download:`Included version <../../tendril/dox/templates/\
customs/authorization.fedex.tex>`)
        * - DHL India
          - ``tendril/dox/templates/customs/authorization.dhl.tex``
          - (:download:`Included version <../../tendril/dox/templates/\
customs/authorization.dhl.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at,
            from :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`
        * - ``sno``
          - The serial number of the document.

    """
    outpath = os.path.join(
        target_folder,
        "customs-authorization-" + str(invoice.inv_no) + ".pdf"
    )
    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': invoice.given_data,
             'sno': serialno + '.1'
             }

    if invoice.given_data['cha'] == 'DHL':
        template = 'customs/authorization.dhl.tex'
    elif invoice.given_data['cha'] == 'FedEx':
        template = 'customs/authorization.fedex.tex'
    else:
        raise ValueError('CHA unsupported')
    return render.render_pdf(stage, template, outpath)
Example #20
0
def gen_valuation(invoice, target_folder, serialno):
    """
    Generates the Customs Valuation Note.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file path

    .. rubric:: Template Used

    ``tendril/dox/templates/customs/valuation.tex``
    (:download:`Included version
    <../../tendril/dox/templates/customs/valuation.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at, from
            :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`
        * - ``currency``
          - The symbol of the currency of the invoice.
        * - ``inv_total``
          - The total value of the invoice, in vendor currency.
        * - ``exchrate``
          - The applicable exchange rate.
        * - ``exchnotif``
          - The government notification number specifying the exchange rate.
        * - ``exchnotifdt``
          - The date of the exchange rate notification.
        * - ``note1``
          - A note mentioning the inclusion of freight.
        * - ``note2``
          - A list of strings mentioning other additions to the valuation.
        * - ``include_note2``
          - Boolean, whether or not to include note2.
        * - ``extended_total_sc``
          - The extended total invoice value, in the vendor's currency.
        * - ``assessable_total_sc``
          - The assessable total invoice value, in the vendor's currency.
        * - ``assessable_total_nc``
          - The assessable total invoice value, in the vendor's currency.
        * - ``copyt``
          - The string specifying which copy it is.
        * - ``sno``
          - The serial number of the document.
        * - ``is_wire``
          - Bool, whether the payment was made by a wire transfer.

    """
    outpath = os.path.join(
        target_folder,
        "customs-valuation-" + str(invoice.inv_no) + ".pdf"
    )

    note1 = ''
    if invoice.includes_freight is True:
        note1 += "As listed in the invoice, {0} towards freight " \
                 "is also added. ".format(invoice.freight.source_string)
    note1 = render.escape_latex(note1)

    note2 = []

    if invoice.added_insurance is True:
        note2.append(
            "An additional {0}% of FOB is added to the assessable value "
            "as per Rule 10(2)(c)(iii) of Customs Valuation "
            "(Determination of Value of Imported Goods) Rules, 2007. "
            "No specific insurance charges were paid as part of the"
            " transaction.".format(invoice.insurance_pc)
        )
    if invoice.added_handling is True:
        note2.append(
            "An additional {0}% of CIF is added to the assessable value "
            "as per Rule 10(2)(b)(ii) of Customs Valuation "
            "(Determination of Value of Imported Goods) Rules, 2007. "
            "No specific handling charges were paid as part of the"
            " transaction.".format(invoice.handling_pc)
        )

    include_note2 = False
    if len(note2) > 0:
        include_note2 = True
    if invoice.given_data['bank_ref'] is None:
        is_wire = False
    else:
        is_wire = True

    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': invoice.given_data,
             'currency': render.escape_latex(invoice.currency.symbol),
             'inv_total':
             render.escape_latex(invoice.extendedtotal.source_string),
             'exchrate': invoice.given_data['exchrate'],
             'exchnotif': invoice.given_data['exchnotif'],
             'exchnotifdt': invoice.given_data['exchnotif_date'],
             'note1': note1,
             'note2': note2,
             'include_note2': include_note2,
             'extended_total_sc':
             render.escape_latex(invoice.extendedtotal.source_string),
             'assessable_total_sc':
             render.escape_latex(invoice.assessabletotal.source_string),
             'assessable_total_nc':
             render.escape_latex(invoice.assessabletotal.native_string),
             'sno': serialno + '.3',
             'is_wire': is_wire
             }

    return render.render_pdf(stage, 'customs/valuation.tex', outpath)
Example #21
0
def gen_confdoc(projfolder, configname, force=False):
    """
    Generate a PDF documenting a single configuration of the project. The
    document should include a reasonably thorough representation of the
    contents of the configuration related sections of the
    `tendril.gedaif.conffile.ConfigsFile``.

    :param projfolder: The gEDA project folder
    :type projfolder: str
    :param configname: The configuration name for which the BOM should be
                       generated.
    :type configname: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/confdocs/<configname>-doc.pdf``
    * Source Files : The project's schematic folder.

    .. rubric:: Template Used

    ``tendril/dox/templates/projects/geda-conf-doc.tex``
    (:download:`Included version
    <../../tendril/dox/templates/projects/geda-conf-doc.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``configname``
          - The name of the configuration (a card or cable name).
        * - ``desc``
          - The description of the configuration.
        * - ``pcbname``
          - The name of the base PCB.
        * - ``obom``
          - An :mod:`tendril.boms.outputbase.OutputBom` instance

    """
    gpf = projfile.GedaProjectFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    docfolder = get_project_doc_folder(projfolder)
    outpath = path.join(docfolder, 'confdocs', configname + '-doc.pdf')
    outf_mtime = fsutils.get_file_mtime(outpath, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + outpath)
        return outpath

    logger.info('Regenerating ' + outpath + os.linesep +
                'Last modified : ' + str(sch_mtime) +
                '; Last Created : ' + str(outf_mtime))
    bom = boms_electronics.import_pcb(projfolder)
    obom = bom.create_output_bom(configname)
    group_oboms = bom.get_group_boms(configname)
    stage = {'configname': obom.descriptor.configname,
             'pcbname': obom.descriptor.pcbname,
             'bom': bom,
             'obom': obom,
             'group_oboms': group_oboms}

    config = obom.descriptor.configurations.configuration(configname)
    stage['desc'] = config['desc']

    template = 'projects/geda-conf-doc.tex'

    workspace_outpath = workspace_fs.getsyspath(outpath)
    workspace_fs.makedir(path.dirname(outpath),
                         recursive=True, allow_recreate=True)
    render.render_pdf(stage, template, workspace_outpath)
    copyfile(workspace_fs, outpath, refdoc_fs, outpath, overwrite=True)

    return outpath
Example #22
0
def render():
    t1 = time.time()
    lang = request.form['lang']
    source = request.form['source']
    mode = request.form['mode']
    fmt = request.form['format']
    background = str(request.form['background'])
    alpha = request.form.get('alpha', 'off') == "on"
    if request.form.get('restrictWidth', 'off') == "on":
        width = int(request.form['width'])
    else:
        width = None
    if request.form.get('restrictHeight', 'off') == "on":
        height = int(request.form['height'])
    else:
        height = None

    request_params = frozenset(
        [lang, source, mode, fmt, background, alpha,
         time.time()])

    # Generate a correlation id for debugging
    app.extensions['correlation_id'] = hash(request_params)

    # Wrap the logger with some request context
    logger = logging.getLogger("source2Image")
    logger = logging.LoggerAdapter(logger, app.extensions)

    # Input validation
    assert fmt in formats
    assert lang in languages
    assert width <= 2048
    assert height <= 2048

    logger.info("Begin handle of request")

    wd = tempfile.mkdtemp()
    logger.info("Creating temp directory %s" % wd)

    # Sanitize the LaTeX source
    if '\end{lstlisting}' in source:
        source = source.replace('\end{lstlisting}',
                                '%\\textbackslash)end{lstlisting}')

    latexTmpl = texenv.get_template("source-listing.tex")
    latexBody = latexTmpl.render(lang=lang, source=source)

    # Generate PDF
    pdfPath = render_pdf(latexBody, wd)
    if not pdfPath:
        abort(503)

    # Determine the correct output, convert with ImageMagick if necessary
    if fmt == "pdf":
        fileBytes = open(pdfPath, "r").read()
        contentType = "application/pdf"
        fileName = "%s-listing.pdf" % lang.lower()
    elif fmt == "png":
        outPath = convert(pdfPath,
                          "texput.png",
                          wd,
                          alpha=alpha,
                          background=background,
                          resize=(width, height))
        if not outPath:
            abort(503)
        else:
            fileBytes = open(outPath, "r").read()
            contentType = "image/png"
            fileName = "%s-listing.png" % lang.lower()
    elif fmt == "jpg":
        outPath = convert(pdfPath,
                          "texput.jpg",
                          wd,
                          alpha=False,
                          background=background,
                          resize=(width, height))
        if not outPath:
            abort(503)
        else:
            fileBytes = open(outPath, "r").read()
            contentType = "image/jpeg"
            fileName = "%s-listing.jpg" % lang.lower()

    # Make the response
    resp = make_response(fileBytes)
    resp.headers["Content-Type"] = contentType

    if mode == "download":
        resp.headers[
            "Content-Disposition"] = "attachment; filename=%s" % fileName

    logger.info("Removing %s" % wd)
    shutil.rmtree(wd)
    t2 = time.time()
    logger.info("End handle of request. Finished in %0.2fs" % (t2 - t1))
    return resp
Example #23
0
def gen_stock_idt_from_cobom(outfolder,
                             sno,
                             title,
                             carddict,
                             cobom,
                             verbose=True):
    """
    Generates a stock indent from a
    :class:`tendril.boms.outputbase.CompositeOutputBom` instance. This
    function also adds ``IDT`` labels for all the stock / inventory items that
    are requested for by the indent to the
    :data:`tendril.dox.labelmaker.manager`, though the caller should make sure
    that the labels are written out after the fact.

    .. note::
        This function does not register the document in the
        :mod:`tendril.dox.docstore`. You should use the output file path
        (returned by this function) to register the document when desired.

    :param outfolder: The folder within which the output PDF should
                      be created.
    :type outfolder: str
    :param sno: The serial number of the Indent
    :type sno: str
    :param title: The title of the Indent
    :param carddict: Either a pre-constructed string, or a dictionary
                     containing the list of card types included for
                     the indent (keys) and the quantity for each (values).
    :type carddict: dict or str
    :param cobom: The composite output BOM, including the BOMs for the cards
                  that the indent is being constructed for.
    :type cobom: :class:`tendril.boms.outputbase.CompositeOutputBom`
    :return: The output file path.

    .. rubric:: Template Used

    ``tendril\dox\\templates\indent_stock_template.tex``
    (:download:`Included version
    <../../tendril/dox/templates/indent_stock_template.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``sno``
          - The serial number of the indent.
        * - ``title``
          - Whether the device is a PCB or a Cable.
        * - ``lines``
          - List of dictionaries, each containing the ``ident`` and ``qty``
            of one line in the indent.
        * - ``cards``
          - A string listing out the various cards the indent was generated
            to request components for.

    """
    outpath = os.path.join(outfolder, str(sno) + '.pdf')
    cards = ""
    if isinstance(carddict, dict):
        for card, qty in sorted(carddict.iteritems()):
            cards += card + ' x' + str(qty) + ', '
    elif isinstance(carddict, str):
        cards = carddict

    indentsno = sno

    lines = []
    for idx, line in enumerate(cobom.lines):
        lines.append({'ident': line.ident, 'qty': line.quantity})

    stage = {'title': title, 'sno': indentsno, 'lines': lines, 'cards': cards}

    template = 'indent_stock_template.tex'
    render.render_pdf(stage, template, outpath, verbose=verbose)

    return outpath, indentsno
Example #24
0
def render_device_summary(devicetype, include_failed=False, outfolder=None):
    """
    Renders a summary of all of the latest test results marked against the
    serial numbers of the specified ``devicetype``.

    :param devicetype: The type of device for which a summary is desired.
    :type devicetype: str
    :param outfolder: The folder in which the output file should be created.
    :type outfolder: str
    :param include_failed: Whether failed test results should be included in
                      the graphs and the statistical analysis. Default False.
    :type include_failed: bool
    :return: The output file path.

    .. rubric:: Template Used

    ``tendril/dox/templates/testing/test_device_summary_template.tex``
    (:download:`Included version
    <../../tendril/dox/templates/testing/test_device_summary_template.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``devicetype``
          - The device type.
        * - ``desc``
          - The device description.
        * - ``svnrevision``
          - The VCS revision of the project config file.
        * - ``svnrepo``
          - The VCS repository containing the project
        * - ``graphs``
          - A list of graphs, each graph being a list of tuples of
            (graphpath, graphtitle)
        * - ``collector``
          - An instance of :class:`tendril.testing.analysis.ResultCollector`,
            containing the collated test results.

    .. seealso:: :func:`tendril.testing.analysis.get_device_test_summary`

    """
    if outfolder is None:
        outfolder = os.path.join(INSTANCE_ROOT, 'scratch', 'testing')
    template = os.path.join('testing', 'test_device_summary_template.tex')
    outpath = os.path.join(outfolder,
                           'TEST-DEVICE-SUMMARY-' + devicetype + '.pdf')

    projectfolder = projects.cards[devicetype]
    gcf = ConfigsFile(projectfolder)

    summary = analysis.get_device_test_summary(devicetype=devicetype,
                                               include_failed=include_failed)
    graphs = summary.graphs

    stage = {
        'devicetype': devicetype,
        'desc': gcf.description(devicetype),
        'svnrevision': vcs.get_path_revision(projectfolder),
        'svnrepo': vcs.get_path_repository(projectfolder),
        'graphs': graphs,
        'collector': summary
    }

    return render_pdf(stage, template, outpath)
Example #25
0
def render_device_summary(devicetype, include_failed=False, outfolder=None):
    """
    Renders a summary of all of the latest test results marked against the
    serial numbers of the specified ``devicetype``.

    :param devicetype: The type of device for which a summary is desired.
    :type devicetype: str
    :param outfolder: The folder in which the output file should be created.
    :type outfolder: str
    :param include_failed: Whether failed test results should be included in
                      the graphs and the statistical analysis. Default False.
    :type include_failed: bool
    :return: The output file path.

    .. rubric:: Template Used

    ``tendril/dox/templates/testing/test_device_summary_template.tex``
    (:download:`Included version
    <../../tendril/dox/templates/testing/test_device_summary_template.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``devicetype``
          - The device type.
        * - ``desc``
          - The device description.
        * - ``svnrevision``
          - The VCS revision of the project config file.
        * - ``svnrepo``
          - The VCS repository containing the project
        * - ``graphs``
          - A list of graphs, each graph being a list of tuples of
            (graphpath, graphtitle)
        * - ``collector``
          - An instance of :class:`tendril.testing.analysis.ResultCollector`,
            containing the collated test results.

    .. seealso:: :func:`tendril.testing.analysis.get_device_test_summary`

    """
    if outfolder is None:
        outfolder = os.path.join(INSTANCE_ROOT, 'scratch', 'testing')
    template = os.path.join('testing', 'test_device_summary_template.tex')
    outpath = os.path.join(outfolder,
                           'TEST-DEVICE-SUMMARY-' + devicetype + '.pdf')

    projectfolder = projects.cards[devicetype]
    gcf = ConfigsFile(projectfolder)

    summary = analysis.get_device_test_summary(devicetype=devicetype,
                                               include_failed=include_failed)
    graphs = summary.graphs

    stage = {'devicetype': devicetype,
             'desc': gcf.description(devicetype),
             'svnrevision': vcs.get_path_revision(projectfolder),
             'svnrepo': vcs.get_path_repository(projectfolder),
             'graphs': graphs,
             'collector': summary
             }

    return render_pdf(stage, template, outpath)
Example #26
0
def gen_delta_pcb_am(orig_cardname,
                     target_cardname,
                     outfolder=None,
                     sno=None,
                     productionorderno=None,
                     indentsno=None,
                     scaffold=False,
                     verbose=True,
                     session=None):
    """
    Generates a Delta PCB Assembly Manifest for converting one card to
    another. This is typically only useful when the two cards are very
    closely related and use the same PCB..

    In the present implementation, the cardname could represent either a PCB
    or a Cable.

    .. note::
        This function does not register the document in the
        :mod:`tendril.dox.docstore`. You should use the output file path
        (returned by this function) to register the document when desired.

    .. seealso::
        - :mod:`tendril.entityhub.projects`, for information about 'cards'

    .. todo:: Update this function to also handle registering once the main
              scripts are better integrated into the core.

    :param orig_cardname: The name of the original card. This should be
                              present in :data:`entityhub.projects.cards`
    :type orig_cardname: str
    :param target_cardname: The name of the target card. This should be
                              present in :data:`entityhub.projects.cards`
    :type target_cardname: str
    :param outfolder: The folder within which the output file should be
                      created.
    :type outfolder: str
    :param sno: The serial number of the card for which you want the Delta
                Assembly Manifest.
    :type sno: str
    :param productionorderno: The serial number of the Production Order for
                              the modification.
    :type productionorderno: str
    :param indentsno: The serial number of the Stock Indent which accounts for
                      the components used in this card.
    :type indentsno: str
    :return: The path of the generated file.

    .. rubric:: Template Used

    ``tendril/dox/templates/production/delta-assem-manifest.tex``
    (:download:`Included version
    <../../tendril/dox/templates/production/delta-assem-manifest.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``sno``
          - The serial number of the card.
        * - ``orig_configname``
          - The configuration name of the original card.
        * - ``target_configname``
          - The configuration name of the target card.
        * - ``pcbname``
          - The name of the original PCB.
        * - ``title``
          - Whether the device is a PCB or a Cable.
        * - ``desc``
          - The description of the modification.
        * - ``addition_lines``
          - List of :class:`tendril.boms.outputbase.OutputBomLine` instances.
        * - ``subtraction_lines``
          - List of :class:`tendril.boms.outputbase.OutputBomLine` instances.
        * - ``stockindent``
          - The serial number of the Stock Indent which accounts for
            the components used in this card.
        * - ``productionorderno``
          - The serial number of the Production Order for the card.
        * - ``original_repopath``
          - The root of the VCS repository which contains the original gEDA project.
        * - ``target_repopath``
          - The root of the VCS repository which contains the target gEDA project.
        * - ``evenpages``
          - Whether to render PDF with even number of pages by adding an extra
            page if needed (useful for bulk printing).

    """

    if outfolder is None:
        from tendril.utils.config import INSTANCE_ROOT
        outfolder = os.path.join(INSTANCE_ROOT, 'scratch', 'production')

    if sno is None:
        # TODO Generate real S.No. here
        sno = 1

    outpath = os.path.join(
        outfolder, 'dm-' + orig_cardname + '->' + target_cardname + '-' +
        str(sno) + '.pdf')

    orig_instance = get_module_instance(sno,
                                        orig_cardname,
                                        session=session,
                                        scaffold=True)
    orig_obom = orig_instance.obom
    target_instance = get_module_prototype(target_cardname)
    target_obom = target_instance.obom

    delta_obom = DeltaOutputBom(orig_obom, target_obom)

    if projects.check_module_is_card(orig_cardname):
        orig_entityname = orig_instance.pcbname
        try:
            target_entityname = target_instance.pcbname
        except AttributeError:
            logger.error("Target for the delta should be a PCB!")
            raise
        title = 'PCB '
        evenpages = True
    elif projects.check_module_is_cable(orig_cardname):
        orig_entityname = orig_instance.cblname
        try:
            target_entityname = target_instance.cblname
        except AttributeError:
            logger.error("Target for the delta should be a Cable!")
            raise
        title = 'Cable '
        evenpages = False
    else:
        raise ValueError

    stage = {
        'orig_configname': orig_cardname,
        'target_configname': target_cardname,
        'pcbname': orig_entityname,
        'title': title,
        'sno': sno,
        'addition_lines': delta_obom.additions_bom.lines,
        'subtraction_lines': delta_obom.subtractions_bom.lines,
        'evenpages': evenpages,
        'stockindent': indentsno,
        'orig_repopath': projects.get_project_repo_repr(orig_cardname),
        'target_repopath':
        projects.get_project_repo_repr(target_cardname),  # noqa
        'productionorderno': productionorderno,
        'desc': delta_obom.descriptor.configname
    }

    template = 'production/delta-assem-manifest.tex'

    render.render_pdf(stage, template, outpath, verbose=verbose)
    return outpath
Example #27
0
def gen_pcb_am(configname, outfolder, sno=None, productionorderno=None,
               indentsno=None, scaffold=False, verbose=True, session=None):
    """
    Generates a PCB Assembly Manifest for a 'card', a card being defined as a
    gEDA project, with a specified ``configname``.

    In the present implementation, the project could provide either a PCB or a
    Cable.

        - In case the project provides the card, the schematic for the cable
          is included along with the assembly manifest.
        - In case the project provides a PCB, the schematic is not included
          with the assembly manifest.

    This behavior is not really intuitive nor universally desirable. This
    rationale should be changed to something that makes more sense.

    .. note::
        This function does not register the document in the
        :mod:`tendril.dox.docstore`. You should use the output file path
        (returned by this function) to register the document when desired.

    .. seealso::
        - :mod:`tendril.gedaif.conffile`, for information about confignames.
        - :mod:`tendril.entityhub.projects`, for information about 'cards'

    .. todo:: Update this function to also handle registering once the main
              scripts are better integrated into the core.

    :param configname: The name of the project configuration to use.
    :type configname: str
    :param outfolder: The folder within which the output file should be
                      created.
    :type outfolder: str
    :param sno: The serial number of the card for which you want the Assembly
                Manifest.
    :type sno: str
    :param productionorderno: The serial number of the Production Order for
                              the card.
    :type productionorderno: str
    :param indentsno: The serial number of the Stock Indent which accounts for
                      the components used in this card.
    :type indentsno: str
    :return: The path of the generated file.

    .. rubric:: Template Used

    ``tendril/dox/templates/production/pcb-assem-manifest.tex``
    (:download:`Included version
    <../../tendril/dox/templates/production/pcb-assem-manifest.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``sno``
          - The serial number of the card.
        * - ``configname``
          - The configuration name of the card.
        * - ``pcbname``
          - The name of the PCB provided by the gEDA project.
        * - ``title``
          - Whether the device is a PCB or a Cable.
        * - ``desc``
          - The description of the card.
        * - ``lines``
          - List of :class:`tendril.boms.outputbase.OutputBomLine` instances.
        * - ``stockindent``
          - The serial number of the Stock Indent which accounts for
            the components used in this card.
        * - ``productionorderno``
          - The serial number of the Production Order for the card.
        * - ``repopath``
          - The root of the VCS repository which contains the gEDA project.
        * - ``evenpages``
          - Whether to render PDF with even number of pages by adding an extra
            page if needed (useful for bulk printing).

    """
    if sno is None:
        # TODO Generate real S.No. here
        sno = 1

    outpath = os.path.join(outfolder,
                           'am-' + configname + '-' + str(sno) + '.pdf')

    instance = get_module_instance(sno, configname,
                                   scaffold=scaffold, session=session)
    obom = instance.obom

    if projects.check_module_is_card(configname):
        entityname = instance.pcbname
        title = 'PCB '
        evenpages = True
        add_schematic = False
    elif projects.check_module_is_cable(configname):
        entityname = instance.cblname
        title = 'Cable '
        evenpages = False
        add_schematic = True
    else:
        raise ValueError

    stage = {'configname': obom.descriptor.configname,
             'pcbname': entityname,
             'title': title,
             'sno': sno,
             'lines': obom.lines,
             'evenpages': evenpages,
             'stockindent': indentsno,
             'repopath': projects.get_project_repo_repr(configname),
             'productionorderno': productionorderno}

    for config in obom.descriptor.configurations.configurations:
        if config['configname'] == configname:
            stage['desc'] = config['desc']

    template = 'production/pcb-assem-manifest.tex'

    render.render_pdf(stage, template, outpath, verbose=verbose)

    if add_schematic is True:
        merge_pdf([outpath,
                   os.path.join(instance.projfolder, 'doc',
                                entityname + '-schematic.pdf')],
                  outpath)
    return outpath
Example #28
0
def gen_pcb_am(configname,
               outfolder,
               sno=None,
               productionorderno=None,
               indentsno=None,
               scaffold=False,
               verbose=True,
               session=None):
    """
    Generates a PCB Assembly Manifest for a 'card', a card being defined as a
    gEDA project, with a specified ``configname``.

    In the present implementation, the project could provide either a PCB or a
    Cable.

        - In case the project provides the card, the schematic for the cable
          is included along with the assembly manifest.
        - In case the project provides a PCB, the schematic is not included
          with the assembly manifest.

    This behavior is not really intuitive nor universally desirable. This
    rationale should be changed to something that makes more sense.

    .. note::
        This function does not register the document in the
        :mod:`tendril.dox.docstore`. You should use the output file path
        (returned by this function) to register the document when desired.

    .. seealso::
        - :mod:`tendril.gedaif.conffile`, for information about confignames.
        - :mod:`tendril.entityhub.projects`, for information about 'cards'

    .. todo:: Update this function to also handle registering once the main
              scripts are better integrated into the core.

    :param configname: The name of the project configuration to use.
    :type configname: str
    :param outfolder: The folder within which the output file should be
                      created.
    :type outfolder: str
    :param sno: The serial number of the card for which you want the Assembly
                Manifest.
    :type sno: str
    :param productionorderno: The serial number of the Production Order for
                              the card.
    :type productionorderno: str
    :param indentsno: The serial number of the Stock Indent which accounts for
                      the components used in this card.
    :type indentsno: str
    :return: The path of the generated file.

    .. rubric:: Template Used

    ``tendril/dox/templates/production/pcb-assem-manifest.tex``
    (:download:`Included version
    <../../tendril/dox/templates/production/pcb-assem-manifest.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``sno``
          - The serial number of the card.
        * - ``configname``
          - The configuration name of the card.
        * - ``pcbname``
          - The name of the PCB provided by the gEDA project.
        * - ``title``
          - Whether the device is a PCB or a Cable.
        * - ``desc``
          - The description of the card.
        * - ``lines``
          - List of :class:`tendril.boms.outputbase.OutputBomLine` instances.
        * - ``stockindent``
          - The serial number of the Stock Indent which accounts for
            the components used in this card.
        * - ``productionorderno``
          - The serial number of the Production Order for the card.
        * - ``repopath``
          - The root of the VCS repository which contains the gEDA project.
        * - ``evenpages``
          - Whether to render PDF with even number of pages by adding an extra
            page if needed (useful for bulk printing).

    """
    if sno is None:
        # TODO Generate real S.No. here
        sno = 1

    outpath = os.path.join(outfolder,
                           'am-' + configname + '-' + str(sno) + '.pdf')

    instance = get_module_instance(sno,
                                   configname,
                                   scaffold=scaffold,
                                   session=session)
    obom = instance.obom

    if projects.check_module_is_card(configname):
        entityname = instance.pcbname
        title = 'PCB '
        evenpages = True
        add_schematic = False
    elif projects.check_module_is_cable(configname):
        entityname = instance.cblname
        title = 'Cable '
        evenpages = False
        add_schematic = True
    else:
        raise ValueError

    stage = {
        'configname': obom.descriptor.configname,
        'pcbname': entityname,
        'title': title,
        'sno': sno,
        'lines': obom.lines,
        'evenpages': evenpages,
        'stockindent': indentsno,
        'repopath': projects.get_project_repo_repr(configname),
        'productionorderno': productionorderno
    }

    for config in obom.descriptor.configurations.configurations:
        if config['configname'] == configname:
            stage['desc'] = config['desc']

    template = 'production/pcb-assem-manifest.tex'

    render.render_pdf(stage, template, outpath, verbose=verbose)

    if add_schematic is True:
        merge_pdf([
            outpath,
            os.path.join(instance.projfolder, 'doc',
                         entityname + '-schematic.pdf')
        ], outpath)
    return outpath
Example #29
0
def gen_verification_checklist(invoice, target_folder, serialno):
    """
    Generates the Customs Duties / Checklist Verification document.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file tuple (path, type)

    .. rubric:: Template Used

    ``tendril/dox/templates/customs/verification-duties.tex``
    (:download:`Included version
    <../../tendril/dox/templates/customs/verification-duties.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at,
            from :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`.
        * - ``lines``
          - A list of :class:`tendril.sourcing.customs.CustomsInvoiceLine`
            instances.
        * - ``invoice``
          - The :class:`tendril.sourcing.customs.CustomsInvoice` instance.
        * - ``sno``
          - The serial number of the document.
        * - ``summary``
          - A list of dicts containing the summary of the customs duties
            applicable against a particular section, as described below

    .. list-table:: Summary keys

        * - ``section``
          - The HS section, a
            :class:`tendril.sourcing.customs.CustomsSection`` instance.
        * - ``code``
          - The HS section code.
        * - ``name``
          - The HS section name.
        * - ``idxs``
          - Line numbers classified into this line.
        * - ``qty``
          - Total quantity of all lines classified into this line.
        * - ``assessablevalue``
          - Total assessable value of all lines classified into this line.
        * - ``bcd``
          - Total Basic Customs Duty applicable against this section.
        * - ``cvd``
          - Total Countervailing Duty applicable against this section.
        * - ``acvd``
          - Total Additional Countervailing Duty applicable against
            this section.
        * - ``cec``
          - Total Education Cess on Customs Duty applicable against
            this section.
        * - ``cshec``
          - Total Secondary and Higher Education Cess on Customs Duty
            applicable against this section.
        * - ``cvdec``
          - Total Education Cess on Countervailing Duty applicable
            against this section.
        * - ``cvdshec``
          - Total Secondary and Higher Education Cess on Countervailing Duty
            applicable against this section.

    """
    print("Generating Customs Duty Verification Checklist")
    outpath = os.path.join(
        target_folder,
        "customs-verification-duties-" + str(invoice.inv_no) + ".pdf"
    )
    summary = []
    pb = TendrilProgressBar(max=len(invoice.hssections))
    print("Collating Section Summaries...")
    for section in invoice.hssections:
        secsum = {'section': section,
                  'code': section.code,
                  'name': section.name,
                  'idxs': invoice.getsection_idxs(hssection=section),
                  'assessablevalue':
                  invoice.getsection_assessabletotal(hssection=section),
                  'qty': invoice.getsection_qty(hssection=section),
                  'bcd':
                  sum([x.bcd.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'cvd':
                  sum([x.cvd.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'acvd':
                  sum([x.acvd.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'cec':
                  sum([x.cec.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'cshec':
                  sum([x.cshec.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'cvdec':
                  sum([x.cvdec.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  'cvdshec':
                  sum([x.cvdshec.value for x in
                       invoice.getsection_lines(hssection=section)]),
                  }
        summary.append(secsum)
        pb.next(note=section.code + ' ' + section.name)
    pb.finish()
    pb = TendrilProgressBar(max=len(invoice.lines))
    pb_summary = TendrilProgressBar(max=len(summary))
    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': invoice.given_data,
             'lines': invoice.lines,
             'summary': summary,
             'invoice': invoice,
             'sno': serialno + '.7',
             'pb': pb,
             'pb_summary': pb_summary}
    print("Rendering...")
    outpath = render.render_pdf(
        stage, 'customs/verification-duties.tex', outpath
    )
    return outpath, 'CUST-VERIF-BOE'
Example #30
0
def gen_declaration(invoice, target_folder, copyt, serialno):
    """
    Generates a copy of the Customs Declaration for Imports.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param copyt: A string specifying which copy it is ("ORIGINAL",
                  "DUPLICATE", so on)
    :type copyt: str
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file path

    .. rubric:: Template Used

    ``tendril/dox/templates/customs/decl.tex``
    (:download:`Included version
    <../../tendril/dox/templates/customs/decl.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at, from
            :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`
        * - ``currency``
          - The symbol of the currency of the invoice.
        * - ``inv_total``
          - The total value of the invoice, in vendor currency.
        * - ``exchrate``
          - The applicable exchange rate.
        * - ``exchnotif``
          - The government notification number specifying the exchange rate.
        * - ``exchnotifdt``
          - The date of the exchange rate notification.
        * - ``extended_total_sc``
          - The extended total invoice value, in the vendor's currency.
        * - ``assessable_total_sc``
          - The assessable total invoice value, in the vendor's currency.
        * - ``assessable_total_nc``
          - The assessable total invoice value, in the vendor's currency.
        * - ``copyt``
          - The string specifying which copy it is.
        * - ``sno``
          - The serial number of the document.

    """
    outpath = os.path.join(
        target_folder,
        "customs-declaration-" + copyt + '-' + str(invoice.inv_no) + ".pdf"
    )

    given_data = copy.deepcopy(invoice.given_data)

    for k, v in given_data['costs_not_included'].iteritems():
        given_data['costs_not_included'][k] = render.escape_latex(v)

    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': given_data,
             'currency': render.escape_latex(invoice.currency.symbol),
             'inv_total':
             render.escape_latex(invoice.extendedtotal.source_string),
             'exchrate': invoice.given_data['exchrate'],
             'exchnotif': invoice.given_data['exchnotif'],
             'exchnotifdt': invoice.given_data['exchnotif_date'],
             'extended_total_sc':
             render.escape_latex(invoice.extendedtotal.source_string),
             'assessable_total_sc':
             render.escape_latex(invoice.assessabletotal.source_string),
             'assessable_total_nc':
             render.escape_latex(invoice.assessabletotal.native_string),
             'copyt': copyt,
             'sno': serialno + '.5'
             }

    return render.render_pdf(stage, 'customs/decl.tex', outpath)
Example #31
0
def gen_valuation(invoice, target_folder, serialno):
    """
    Generates the Customs Valuation Note.

    :param invoice: The invoice object with customs information
    :type invoice: :class:`tendril.sourcing.customs.CustomsInvoice`
    :param target_folder: The folder in which the generated files
                          should be written to
    :param serialno: The serial number of the Customs documentation set
    :type serialno: str
    :return: The output file path

    .. rubric:: Template Used

    ``tendril/dox/templates/customs/valuation.tex``
    (:download:`Included version
    <../../tendril/dox/templates/customs/valuation.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``date``
          - The date the documents were generated at, from
            :func:`datetime.date.today`.
        * - ``signatory``
          - The name of the person who 'signs' the document, from
            :data:`tendril.utils.config.COMPANY_GOVT_POINT`.
        * - ``inv_no``
          - The vendor's invoice number.
        * - ``inv_date``
          - The date of the vendor's invoice.
        * - ``given_data``
          - A dict containing various facts about the invoice. See
            :attr:`tendril.sourcing.customs.CustomsInvoice.given_data`
        * - ``currency``
          - The symbol of the currency of the invoice.
        * - ``inv_total``
          - The total value of the invoice, in vendor currency.
        * - ``exchrate``
          - The applicable exchange rate.
        * - ``exchnotif``
          - The government notification number specifying the exchange rate.
        * - ``exchnotifdt``
          - The date of the exchange rate notification.
        * - ``note1``
          - A note mentioning the inclusion of freight.
        * - ``note2``
          - A list of strings mentioning other additions to the valuation.
        * - ``include_note2``
          - Boolean, whether or not to include note2.
        * - ``extended_total_sc``
          - The extended total invoice value, in the vendor's currency.
        * - ``assessable_total_sc``
          - The assessable total invoice value, in the vendor's currency.
        * - ``assessable_total_nc``
          - The assessable total invoice value, in the vendor's currency.
        * - ``copyt``
          - The string specifying which copy it is.
        * - ``sno``
          - The serial number of the document.
        * - ``is_wire``
          - Bool, whether the payment was made by a wire transfer.

    """
    outpath = os.path.join(
        target_folder,
        "customs-valuation-" + str(invoice.inv_no) + ".pdf"
    )

    note1 = ''
    if invoice.includes_freight is True:
        note1 += "As listed in the invoice, {0} towards freight " \
                 "is also added. ".format(invoice.freight.source_string)
    note1 = render.escape_latex(note1)

    note2 = []

    if invoice.added_insurance is True:
        note2.append(
            "An additional {0}% of FOB is added to the assessable value "
            "as per Rule 10(2)(c)(iii) of Customs Valuation "
            "(Determination of Value of Imported Goods) Rules, 2007. "
            "No specific insurance charges were paid as part of the"
            " transaction.".format(invoice.insurance_pc)
        )
    if invoice.added_handling is True:
        note2.append(
            "An additional {0}% of CIF is added to the assessable value "
            "as per Rule 10(2)(b)(ii) of Customs Valuation "
            "(Determination of Value of Imported Goods) Rules, 2007. "
            "No specific handling charges were paid as part of the"
            " transaction.".format(invoice.handling_pc)
        )

    include_note2 = False
    if len(note2) > 0:
        include_note2 = True
    if invoice.given_data['bank_ref'] is None:
        is_wire = False
    else:
        is_wire = True

    stage = {'date': datetime.date.today().isoformat(),
             'signatory': COMPANY_GOVT_POINT,
             'inv_no': invoice.inv_no,
             'inv_date': invoice.inv_date,
             'given_data': invoice.given_data,
             'currency': render.escape_latex(invoice.currency.symbol),
             'inv_total':
             render.escape_latex(invoice.extendedtotal.source_string),
             'exchrate': invoice.given_data['exchrate'],
             'exchnotif': invoice.given_data['exchnotif'],
             'exchnotifdt': invoice.given_data['exchnotif_date'],
             'note1': note1,
             'note2': note2,
             'include_note2': include_note2,
             'extended_total_sc':
             render.escape_latex(invoice.extendedtotal.source_string),
             'assessable_total_sc':
             render.escape_latex(invoice.assessabletotal.source_string),
             'assessable_total_nc':
             render.escape_latex(invoice.assessabletotal.native_string),
             'sno': serialno + '.3',
             'is_wire': is_wire
             }

    return render.render_pdf(stage, 'customs/valuation.tex', outpath)
Example #32
0
def render_test_report(serialno=None, outfolder=None, session=None):
    """
    Renders the latest test results marked against the specified ``serialno``.

    Since this function is defined against the database, all arguments should
    be keyword arguments.

    :param serialno: The serial number of the device.
    :type serialno: :class:`str` or :class:`tendril.entityhub.db.SerialNumber`
    :param outfolder: The folder in which the output file should be created.
    :type outfolder: str
    :param session: The database session. If None, the function will make
                    it's own.
    :return: The output file path.

    .. rubric:: Template Used

    ``tendril/dox/templates/testing/test_report_template.tex``
    (:download:`Included version
    <../../tendril/dox/templates/testing/test_report_template.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``sno``
          - Serial number of the device.
        * - ``testdate``
          - The timestamp of the latest test suite.
        * - ``devicetype``
          - The device type.
        * - ``desc``
          - The device description.
        * - ``svnrevision``
          - The VCS revision of the project config file.
        * - ``svnrepo``
          - The VCS repository containing the project
        * - ``graphs``
          - A list of graphs, each graph being a list of tuples of
            (graphpath, graphtitle)
        * - ``instruments``
          - A list of instrument ident strings, one for each unique
            instrument used in the suites.
        * - ``suites``
          - A list of instances of
            :class:`tendril.testing.testbase.TestSuiteBase` or its subclasses.

    Note that the ``suites`` provided to the template are typically
    expected to be offline test suites which are reconstructed from the
    database.

    .. seealso:: :func:`tendril.testing.analysis.get_test_suite_objects`

    """
    if serialno is None:
        raise ValueError("serialno cannot be None")
    if not isinstance(serialno, SerialNumber):
        serialno = sno_controller.get_serialno_object(sno=serialno,
                                                      session=session)
    if outfolder is None:
        outfolder = os.path.join(INSTANCE_ROOT, 'scratch', 'testing')

    template = os.path.join('testing', 'test_report_template.tex')
    outpath = os.path.join(outfolder,
                           'TEST-REPORT-' + serialno.sno + '.pdf')

    devicetype = serialnos.get_serialno_efield(sno=serialno.sno,
                                               session=session)
    projectfolder = projects.cards[devicetype]
    gcf = ConfigsFile(projectfolder)

    suites = analysis.get_test_suite_objects(serialno=serialno.sno,
                                             session=session)
    graphs = []
    instruments = {}
    for suite in suites:
        for test in suite._tests:
            graphs.extend(test.graphs)
            graphs.extend(test.histograms)
            if test._inststr is not None and \
                    test._inststr not in instruments.keys():
                instruments[test._inststr] = len(instruments.keys()) + 1

    stage = {'suites': [x.render_dox() for x in suites],
             'sno': serialno.sno,
             'testdate': max([x.ts for x in suites]).format(),
             'devicetype': devicetype,
             'desc': gcf.description(devicetype),
             'svnrevision': vcs.get_path_revision(projectfolder),
             'svnrepo': vcs.get_path_repository(projectfolder),
             'graphs': graphs,
             'instruments': instruments
             }

    return render_pdf(stage, template, outpath)
Example #33
0
def gen_stock_idt_from_cobom(outfolder, sno, title, carddict, cobom, verbose=True):
    """
    Generates a stock indent from a
    :class:`tendril.boms.outputbase.CompositeOutputBom` instance. This
    function also adds ``IDT`` labels for all the stock / inventory items that
    are requested for by the indent to the
    :data:`tendril.dox.labelmaker.manager`, though the caller should make sure
    that the labels are written out after the fact.

    .. note::
        This function does not register the document in the
        :mod:`tendril.dox.docstore`. You should use the output file path
        (returned by this function) to register the document when desired.

    :param outfolder: The folder within which the output PDF should
                      be created.
    :type outfolder: str
    :param sno: The serial number of the Indent
    :type sno: str
    :param title: The title of the Indent
    :param carddict: Either a pre-constructed string, or a dictionary
                     containing the list of card types included for
                     the indent (keys) and the quantity for each (values).
    :type carddict: dict or str
    :param cobom: The composite output BOM, including the BOMs for the cards
                  that the indent is being constructed for.
    :type cobom: :class:`tendril.boms.outputbase.CompositeOutputBom`
    :return: The output file path.

    .. rubric:: Template Used

    ``tendril\dox\\templates\indent_stock_template.tex``
    (:download:`Included version
    <../../tendril/dox/templates/indent_stock_template.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``sno``
          - The serial number of the indent.
        * - ``title``
          - Whether the device is a PCB or a Cable.
        * - ``lines``
          - List of dictionaries, each containing the ``ident`` and ``qty``
            of one line in the indent.
        * - ``cards``
          - A string listing out the various cards the indent was generated
            to request components for.

    """
    outpath = os.path.join(outfolder, str(sno) + '.pdf')
    cards = ""
    if isinstance(carddict, dict):
        for card, qty in sorted(carddict.iteritems()):
            cards += card + ' x' + str(qty) + ', '
    elif isinstance(carddict, str):
        cards = carddict

    indentsno = sno

    lines = []
    for idx, line in enumerate(cobom.lines):
        lines.append({'ident': line.ident, 'qty': line.quantity})

    stage = {'title': title,
             'sno': indentsno,
             'lines': lines,
             'cards': cards}

    template = 'indent_stock_template.tex'
    render.render_pdf(stage, template, outpath, verbose=verbose)

    return outpath, indentsno