{"id":22802733,"url":"https://github.com/buffolander/rappi-payless-conciliation-sample","last_synced_at":"2026-06-23T12:32:57.493Z","repository":{"id":143741847,"uuid":"300366907","full_name":"buffolander/rappi-payless-conciliation-sample","owner":"buffolander","description":null,"archived":false,"fork":false,"pushed_at":"2020-10-13T19:00:46.000Z","size":92,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-01T16:40:41.201Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/buffolander.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-01T17:35:22.000Z","updated_at":"2025-01-29T19:55:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"1ca8840e-e0f6-450f-a435-248253d2f843","html_url":"https://github.com/buffolander/rappi-payless-conciliation-sample","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/buffolander/rappi-payless-conciliation-sample","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buffolander%2Frappi-payless-conciliation-sample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buffolander%2Frappi-payless-conciliation-sample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buffolander%2Frappi-payless-conciliation-sample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buffolander%2Frappi-payless-conciliation-sample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/buffolander","download_url":"https://codeload.github.com/buffolander/rappi-payless-conciliation-sample/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/buffolander%2Frappi-payless-conciliation-sample/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34688116,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-12T09:07:09.110Z","updated_at":"2026-06-23T12:32:57.467Z","avatar_url":"https://github.com/buffolander.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rappi Payless v3 Conciliation ETL\n\nThis is a flexible ETL script commonly used by retailers when reconciling transactions from their integrations with Rappi Payless.\n\nIt's configurable enough to allow...\n\n1. ... consuming Rappi Payless v3 API to extract transactions data for different time frames: daily, weekly, monthly or custom dates, as well as specifying the when the script should run and your local timezone;\n\n2. ... transforming the raw data received from Rappi to comply with your conciliation file schema and conventions;\n\n3. ... loading the data to your FTP server.\n\n## Setting up your `env` file\n\nThe `.env` file located in `/src/build-file/.env`, is your single source for static configurations.\n\nThere are two types of configuration to be setup in this file: (1) your Rappi credentials and (2) access details to your SFTP server.\n\nYou must replace the question mark for actual values on each on these environment variables:\n\n```\n# /src/build-file/.env\n\nRAPPI_RETAILER_ID=?\nRAPPI_RETAILER_SECRET=?\n\nSFTP_HOST=?\nSFTP_PORT=22\nSFTP_USER=?\nSFTP_PASSWORD=?\n```\n\n## Setting up your `config.js` file\n\nThe `/src/build-file/config.js` is the core of your ETL. It allows you to customize fully customize your data extraction, transformation and load.\n\n### Time frame properties\n\nTransactions can be queried in a daily, weekly or monthly basis. Your frequency option is established by the `frequency` property.\n\nIt's also possible to query transactions based custom dates. It enables the script to establish the initial and final dates sent on the http request to Rappi.\n\n**IMPORTANT!**\n\n1. Whatever the chosen frequency, `timezone` is always a required property. It allows transactions' timestamps to be adjusted to you local time.\n\n2. Whenever the `startDate` and `endDate` properties are configured, the script will perform a custom query and all other time frame properties in `config.js` will be ignored.\n\n3. If `frequency` is declared (whatever the value it holds), you must also specify `scheduledTime`. This property tells the script the hour it should be executed.\n\n`frequency: daily` no additional properties required.\n\n`frequency: weekly` additional properties: `dayOfWeek` (string); enum: MON, TUE, WED, THU, FRI, SAT, SUN.\n\n`frequency: monthly` additional properties: `dayOfMonth` (string); accepts the date in format 'DD'.\n\n### **Your file conventions**\n\nFile conventions are properties that allow you to define:\n\n1. The file name mask. Property `fileName` (function);\n\n2. The target directory in your server. Property `targetDirectory` (string);\n\n3. The extension applied to the file. Property `extension` (string);\n\n4. The default value for unavailable data. Property: `defaultUnavailableData` (string | number);\n\n5. The character used for separating columns. Property: `fieldSeparator` (string).\n\n### **Transformation functions**\n\nTransformation functions have slightly different applications in file headers and bodies, but the overall behavior is the same. They take two arguments: `value` (any) and `options` (object).\n\nIn the file header transformation functions work as aggregators. The `value` argument will always be the file body.\n\nFor columns in the file body, transformation functions will change the data a column is mapped against in Rappi's response schema. This transformation maybe as simple as formatting a date or time field, or assigning new values to enumerables, or as complex as you need it to be.\n\nThe `value` argument will always take as input the property outlined in `mapsTo`. It must map to properties in the Rappi Payless v3 listPayments [response schema](https://app.swaggerhub.com/apis/rappi-docs/cpg-public-api/v3#/Payments/listPayments).\n\nThe `options` argument includes function-specific processing instructions, such as the formatting mask in `formatDate` or que index for the column being aggregated in `sumRecords`.\n\nThe script includes two built-in transformation functions for the file header, `countRecords` and `sumRecords`; and three, for columns in the file body. You may implement new ones creating your functions and linking them to the schemas in `config.js`.\n\n```javascript\n// Aggregation function example: header aggregation\nmodule.exports.sumRecords = (value, {\n  index,\n  separator,\n}) =\u003e {\n  const records = value.split('\\n')\n  return empty(records[0]) ? 0 : records.reduce(\n    (acc, cur) =\u003e (acc + Number(cur.split(separator)[index])), 0,\n  )\n}\n\n// File body, column transformation example\nconst m = require('moment-timezone')\n\nconst formatDate = (value, {\n  dateFormat,\n  timezone = null,\n}) =\u003e (timezone\n  ? m.tz(value, timezone).format(dateFormat)\n  : m(value).format(dateFormat)\n)\n```\n\n### **File header**\n\nFile header properties are used for aggregating transactions exported to the file. It's an option not often used by retailers. In case you don't required any aggregation in your conciliation files, `fileHeader` might be omitted from your `config.js` file.\n\nIt has two top-level properties: `labelProperties` (boolean) is a switch to show or hide labels in the header properties; and the `schema` (array) holds all file header fields and their values.\n\nEach header field require a `name` property. It's the printed label value when `labelProperties === true`.\n\nThe header object also requires either a `default` or `transform` property.\n\nThe `default` property accepts a static value or a function that doesn't take no transaction data (fileColumns data) as input.\n\nThe `transform` property is an object that specifies how `fileColumns` data should be aggregated. This object requires a `lambda` property which is your aggregation function, and it also takes an non-required `options` property. The script takes an `options` property and applies it to the related `lambda` as its second argument.\n\n### **File body**\n\nYou'll notice a similar structure in the `fileColumns` property. The noticeable difference lies in the `schema`. Each object in this collection represents a column in your file body.\n\nThere are straightforward mappings to data returned by Rappi or to static values...\n\n```javascript\n    }, { // mapping without transformation\n      name: 'numero_transaccion',\n      mapsTo: 'terminal_transaction_id',\n    }, { // always assign an static value\n      name: 'cedula_rappitendero',\n      default: '0',\n    }],\n```\n\nNext in complexity order are transformations. The `value` argument for a transformation function will always be the data mapped in the property `mapsTo`. In the following example, when the script is executed it will pass the `created_at` value of each transaction returned by Rappi and pass on to the `formatDate` function. This function will also ingest the `dateFormat` and `timezone` options to compute the return value.\n\n```javascript\n    }, {\n      name: 'hora',\n      mapsTo: 'created_at',\n      transform: {\n        lambda: formatDate,\n        options: { dateFormat: 'HHmmss', timezone },\n      },\n    }, {\n```\n\nThe most complex transformation would be one taking multiple response properties to compute its return value. One example is the `parseAmount` function. It takes the property `amount` as `value` argument but it also depends on the property `transaction_type` to calculate its return value. Dependency properties for any transformation function can be passed as a list in the `helpers` property.\n\n```javascript\n    }, {\n      name: 'valor',\n      mapsTo: 'amount',\n      helpers: ['transaction_type'],\n      transform: {\n        lambda: parseAmount,\n        options: { multiplier: 100, signChanger: 'CANCELLATION' },\n      },\n    }, {\n```\n\n## Deploying the script to Google Cloud\n\nPENDING\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbuffolander%2Frappi-payless-conciliation-sample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbuffolander%2Frappi-payless-conciliation-sample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbuffolander%2Frappi-payless-conciliation-sample/lists"}