Skip to main content

Overview

The Bidding and Procurement system manages ESP Santa Fe de Antioquia’s public procurement processes (convocatorias/licitaciones). This comprehensive feature handles the publication of bidding opportunities, manages bidder registration and proposals, and ensures transparency in procurement activities.

Legal Compliance

Colombian law requires public entities to conduct transparent procurement processes. This system ensures compliance with legal requirements while streamlining the bidding workflow.

System Components

The procurement system consists of two main modules:

Bidding Processes

NacionLicitante: Manage procurement opportunities, publish requirements, and track timelines

Bidder Registration

BiddingParticipants: Register interested parties and collect proposal submissions

User Workflows

Creating a Procurement Process

1

Admin Creates Bidding

Administrators create a new procurement process with:
  • Process name/title
  • Detailed description and requirements
  • Start and end dates
  • Featured image or cover
  • Related documents
2

Upload Documents

Attach official documents including:
  • Terms of reference
  • Technical specifications
  • Legal requirements
  • Financial criteria
3

Publication

Process goes live on /convocatorias with active status based on date range
4

Monitor Submissions

Track bidder registrations and proposal submissions throughout the process

Bidder Registration

1

Discover Opportunity

Bidders browse active procurement processes at /convocatorias
2

Review Requirements

Access detailed information at /convocatorias/{nameNacionLicitante}
3

Register Interest

Complete registration form with company/personal details
4

Submit Proposal

Upload proposal documents and receive confirmation code
5

Track Status

Use reference code to check submission status at /convocatorias/reference/{reference}

Data Models

Procurement Process (NacionLicitante)

public class Master  // Used for bidding processes
{
    public int Id { get; set; }
    public string NameMaster { get; set; }                    // Process name
    public string UrlMaster { get; set; }                     // URL slug
    public string Description { get; set; }                   // HTML description
    public string CoverPage { get; set; }                     // Cover image
    public DateTime NacionLicitantegStartDate { get; set; }   // Opening date
    public DateTime NacionLicitanteEndDate { get; set; }      // Closing date
    public Boolean NacionLicitante { get; set; }              // Flag: true for procurement
    public Boolean Statud { get; set; }                       // Published status
    public DateTime DateCreate { get; set; }                  // Creation date
    public DateTime DateUpdate { get; set; }                  // Last update
    
    // Navigation properties
    public IEnumerable<FileDocument> FilesDocuments { get; set; }
    public IEnumerable<Document> DelatedDocuments { get; set; }
}

Bidder Participant

public class BiddingParticipant
{
    public int Id { get; set; }
    public Guid Ref { get; set; }                      // Reference tracking code
    public int MasterId { get; set; }                  // FK to procurement process
    public Boolean NaturalPerson { get; set; }         // True = individual, False = company
    public string Name { get; set; }                   // Bidder name/company
    public string IdentificationOrNit { get; set; }    // ID or tax number
    public string Phone { get; set; }                  // Landline
    public string Cellular { get; set; }               // Mobile
    public string Address { get; set; }                // Physical address
    public string City { get; set; }                   // City location
    public string Email { get; set; }                  // Contact email
    public string Proposals { get; set; }              // Uploaded proposal path
    public DateTime DateCreate { get; set; }           // Submission date
}

Controller Actions - Procurement Processes

Admin Routes

Purpose: Display all procurement processesAccess: SuperAdmin, AdminFeatures:
  • View all processes (active and closed)
  • See start and end dates
  • Monitor creation and update timestamps
[Authorize(Roles = "SuperAdmin,Admin")]
public async Task<IActionResult> Index()
{
    var _model = from a in await _nacionLicitante.GetAll()
                 select new ModelViewNacionLicitante
                 {
                     Id = a.Id,
                     NameMaster = a.NameMaster,
                     UrlMaster = a.UrlMaster,
                     NacionLicitantegStartDate = a.NacionLicitantegStartDate
                         .ToString("MMMM dd, yyyy", 
                         CultureInfo.CreateSpecificCulture("es-CO")),
                     NacionLicitanteEndDate = a.NacionLicitanteEndDate
                         .ToString("MMMM dd, yyyy",
                         CultureInfo.CreateSpecificCulture("es-CO"))
                 };
    return View(_model);
}
Purpose: Create new procurement processAccess: SuperAdmin, AdminValidation:
  • Unique process names
  • Valid date ranges (end after start)
  • Required document uploads
[Authorize(Roles = "SuperAdmin,Admin")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(NacionLicitanteCreateDto model)
{
    var _urlName = _nacionLicitante.DuplicaName(model.NameMaster);

    if (_urlName)
    {
        ViewData["DuplicaName"] = 
            $"El Nombre {model.NameMaster} ya ha sido utilizado, cambielo";
        return View(model);
    }

    if (ModelState.IsValid)
    {
        await _nacionLicitante.Create(model);
        return RedirectToAction(nameof(Index));
    }

    return View(model);
}
Purpose: Remove procurement processAccess: SuperAdmin, AdminWarning: Also deletes all associated bidder registrations and documents

Public Routes

Purpose: Public listing of active procurement processesAccess: PublicFeatures:
  • Shows only published processes (Statud = true)
  • Indicates active status based on current date
  • Displays cover images and key dates
  • Links to detailed information
[Route("convocatorias")]
public async Task<IActionResult> ListGetAll()
{
    var _model = from a in await _nacionLicitante.GetAll()
                 where a.Statud == true
                 select new ModelViewNacionLicitante
                 {
                     Id = a.Id,
                     NameMaster = a.NameMaster,
                     UrlMaster = a.UrlMaster,
                     CoverPage = a.CoverPage,
                     Description = a.Description,
                     NacionLicitantegStartDate = a.NacionLicitantegStartDate.ToString(),
                     NacionLicitanteEndDate = a.NacionLicitanteEndDate.ToString(),
                     Statud = ValidateActivo(a)
                 };
    return View(_model);
}
Purpose: Display complete procurement informationAccess: PublicFeatures:
  • Full description and requirements
  • All attached documents
  • Start and end dates
  • Active/closed status indicator
  • Link to registration form
The system validates active status:
private static bool ValidateActivo(Master _master)
{
    var dateTime = DateTime.Now.Date;
    var statud = false;

    if (dateTime >= _master.NacionLicitantegStartDate)
    {
        if (dateTime <= _master.NacionLicitanteEndDate)
        {
            statud = true;
        }
    }
    return statud;
}
Purpose: Serve official procurement documentsAccess: Public
[Authorize(Roles = "UserApp")]
[AllowAnonymous]
[ActionName("Documento-Oficial-de-la-convocatoria")]
public FileResult OfficialLicitante(string routeFile)
{
    return File($"/images/filesDocuments/{routeFile}", 
                "application/pdf", 
                $"{routeFile}.pdf");
}

Controller Actions - Bidder Management

Admin Routes

Purpose: View all bidder registrationsAccess: SuperAdmin, AdminFeatures:
  • Complete list across all processes
  • Shows associated procurement process
  • Reference codes for tracking
  • Submission dates
[Authorize(Roles = "SuperAdmin,Admin")]
public async Task<IActionResult> Index()
{
    var _biddingParticipantGetAll = await _biddingParticipantService.GetAll();
    var _nacionLicitanteGellGetAll = await _nacionLicitante.GetAll();

    var _model = from a in _biddingParticipantGetAll
                 from b in _nacionLicitanteGellGetAll
                 where a.MasterId == b.Id
                 select new ModelViewBiddingParticipant
                 {
                     Id = a.Id,
                     Ref = a.Ref.ToString(),
                     NaturalPerson = a.NaturalPerson,
                     Name = a.Name,
                     IdentificationOrNit = a.IdentificationOrNit,
                     Email = a.Email,
                     City = a.City,
                     Proposals = a.Proposals,
                     DateCreate = a.DateCreate.ToString("MMMM dd, yyyy",
                         CultureInfo.CreateSpecificCulture("es-CO")),
                     NameNocionLicitante = b.NameMaster
                 };

    return View(_model);
}
Purpose: View complete bidder informationAccess: SuperAdmin, Admin, UserAppDisplays all submitted information and uploaded proposals.
Purpose: Remove invalid or duplicate bidder registrationAccess: SuperAdmin, Admin

Public/Bidder Routes

Purpose: Register interest in procurement processAccess: Public (UserApp role for authenticated users)Validation:
  • Checks for duplicate ID/NIT per process
  • Validates required contact information
  • Ensures proposal file upload
[Authorize(Roles = "SuperAdmin,Admin,UserApp")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(BiddingParticipantCreateDTO model)
{
    int _masterId = Convert.ToInt16(model.MasterId);
    var _identificationOrNit = _biddingParticipantService
        .DuplicaIdentificationOrNit(model.IdentificationOrNit, _masterId);

    if (_identificationOrNit)
    {
        ViewData["DuplicaIdentificationOrNit"] = 
            $"Este documento {model.IdentificationOrNit} ya ha sido utilizado";
        return View(model);
    }

    if (ModelState.IsValid)
    {
        var result = await _biddingParticipantService.Create(model);
        _StatusMessaje = true;
        return RedirectToAction("Details", new {@id = result.Id});
    }
    return View(model);
}
Purpose: Track submission using reference codeAccess: SuperAdmin, Admin, UserAppAllows bidders to verify their submission was received and view confirmation.
Purpose: Download submitted proposal documentsAccess: SuperAdmin, Admin
[Authorize(Roles = "SuperAdmin,Admin")]
[ActionName("Documento-participante")]
public FileResult OfficialLicitante(string nameFile, string routeFile)
{
    return File($"/images/filesBiddingParticipant/{routeFile}", 
                "application/pdf", 
                $"{nameFile}-{DateTime.Now.ToString()}.pdf");
}

Bidder Types

The system supports two types of bidders:

Natural Person

NaturalPerson = trueIndividual bidders with:
  • Personal ID (Cédula)
  • Individual name
  • Personal contact information

Legal Entity

NaturalPerson = falseCompany bidders with:
  • Tax ID (NIT)
  • Company name
  • Corporate contact details

Process Status Logic

Procurement processes have three states:
Current date is before NacionLicitantegStartDate
  • Visible but not accepting submissions
  • Shows “Próximamente” or “Coming Soon”

Reference Code System

Each bidder receives a unique GUID reference code:
public Guid Ref { get; set; }  // e.g., 3fa85f64-5717-4562-b3fc-2c963f66afa6
This code:
  • Confirms successful registration
  • Allows status tracking
  • Protects bidder privacy
  • Facilitates communication with ESP

Document Management

Two types of documents are managed:

Procurement Documents

  • Stored in /images/filesDocuments/
  • PDF format
  • Linked via FileDocument entity
  • Publicly downloadable

Bidder Proposals

  • Stored in /images/filesBiddingParticipant/
  • PDF format
  • Confidential (admin access only)
  • Associated with BiddingParticipant records

Validation Rules

Procurement Process

  • Unique process name
  • End date after start date
  • At least one document attached
  • Valid description and requirements

Bidder Registration

  • Valid email address
  • Phone or cellular required
  • ID/NIT unique per process
  • Proposal document required
  • City and address required

Integration Points

Procurement processes link to documents through:
  • Direct file attachments (FileDocument)
  • References to existing legal documents (DelatedDocuments)
Announce new procurement opportunities through blog posts
Send confirmations to bidders upon successful registration

Compliance & Transparency

This system helps ESP comply with Colombian public procurement regulations including:
  • Law 80 of 1993 (Public Contracting Statute)
  • Law 1150 of 2007 (Public Procurement Reform)
  • Decree 1082 of 2015 (Regulatory framework)
All procurement activities are transparent and publicly accessible.

Build docs developers (and LLMs) love