Skip to content

Commit

Permalink
Tag numbers in csv
Browse files Browse the repository at this point in the history
  • Loading branch information
mbayopanda committed Feb 3, 2022
1 parent 0300cdb commit f2358a7
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 0 deletions.
3 changes: 3 additions & 0 deletions client/src/i18n/en/form.json
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
"SHOWING": "Showing",
"SUCCESS":"Operation successfully completed",
"SUPPORT_COST": " is paid by:",
"TAG_NUMBERS_TO_GENERATE": "Generates unique tag numbers that you can put on your goods before counting them in your stock",
"THE_LAST_5_INVOICES": "The last 5 invoices",
"THE_NECESSARY_CONFIG_MISSING": "The necessary configurations are missing",
"THIS_INVOICE_NO_STOCK": "This invoice does not concern any item in stock",
Expand Down Expand Up @@ -293,6 +294,7 @@
"AMOUNT_PAID" : "Amount Paid",
"ARTICLES":"Articles",
"CASHBOXES": "Cashboxes",
"NUMBER_OF_TAGS": "Number of tags",
"SELECT_ALL_LOTS": "Select all lots",
"MERGE_LOCATIONS": "Merge Locations",
"MERGE_LOCATIONS_TO_ONE":"Merge locations into one location",
Expand Down Expand Up @@ -948,6 +950,7 @@
"FILTER_BY": "Filter by",
"SEARCH_NAME": "Search by Name",
"SEARCH_PATIENT_ID": "Search by Patient ID",
"TAG_NUMBER_TO_GENERATE" : "Enter the number of tags to produce",
"QUANTITY": "Enter a quantity"
},
"SELECT": {
Expand Down
1 change: 1 addition & 0 deletions client/src/i18n/en/stock.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"ENTRY_PURCHASE" : "Purchase",
"ENTRY_TRANSFER" : "Transfer",
"EXPIRED" : "Expired",
"GENERATE_TAG_NUMBERS" : "Generate Tag Numbers",
"GLOBAL_LOT_DESCRIPTION" : "Global lot description",
"GLOBAL_EXPIRATION_DATE" : "Global expiration date",
"STOCK_EXPIRED_WARNING" : "Alert : there are {{total}} expired products",
Expand Down
3 changes: 3 additions & 0 deletions client/src/i18n/fr/form.json
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
"SHOWING": "Aperçue",
"SUCCESS":"Opération realisée avec succès",
"SUPPORT_COST": " est prise en charge par",
"TAG_NUMBERS_TO_GENERATE": "Génère des numéros d'étiquettes unique que vous pouvez poser sur vos biens avant de les comptabiliser dans votre stock",
"THE_LAST_5_INVOICES": "Les 5 dernières factures",
"THE_NECESSARY_CONFIG_MISSING": "Les configurations nécessaires manquent",
"THIS_INVOICE_NO_STOCK": "Cette facture ne concerne aucun article en stock",
Expand Down Expand Up @@ -294,6 +295,7 @@
"ARTICLES":"Articles",
"CASHBOXES": "Caisses",
"DEBTOR_GROUP_OPTIONAL": "Groupe débiteur (optionel)",
"NUMBER_OF_TAGS": "Nombre des étiquettes",
"SELECT_ALL_LOTS": "Sélectionner tous les lots",
"MERGE_LOCATIONS": "Fusionner les localisations",
"MERGE_LOCATIONS_TO_ONE":"Fusionner les localisations en une seule localisation",
Expand Down Expand Up @@ -949,6 +951,7 @@
"FILTER_BY": "Filtrer par",
"SEARCH_NAME": "Chercher Par Nom",
"SEARCH_PATIENT_ID": "Chercher par l'ID",
"TAG_NUMBER_TO_GENERATE" : "Entrer le nombre des étiquettes à produire",
"QUANTITY": "Entrer le Quantité"
},
"SELECT": {
Expand Down
1 change: 1 addition & 0 deletions client/src/i18n/fr/stock.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"ENTRY_PURCHASE" : "Achat",
"ENTRY_TRANSFER" : "Transfert",
"EXPIRED" : "Expiré",
"GENERATE_TAG_NUMBERS" : "Générer numéro d'étiquette",
"GLOBAL_LOT_DESCRIPTION" : "Déscription lot global",
"GLOBAL_EXPIRATION_DATE" : "Expiration globale",
"STOCK_EXPIRED_WARNING" : "Alert : il y a {{total}} produits expirés",
Expand Down
98 changes: 98 additions & 0 deletions client/src/js/services/DownloadLink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
angular.module('bhima.services')
.service('DownloadLinkService', DownloadLinkService);

// dependencies injection
DownloadLinkService.$inject = [];

// service definition
function DownloadLinkService() {
const service = this;

const typeMime = {
aac : 'audio/aac',
abw : 'application/x-abiword',
arc : 'application/octet-stream',
avi : 'video/x-msvideo',
azw : 'application/vnd.amazon.ebook',
bin : 'application/octet-stream',
bmp : 'image/bmp',
bz : 'application/x-bzip',
bz2 : 'application/x-bzip2',
csh : 'application/x-csh',
css : 'text/css',
csv : 'text/csv',
doc : 'application/msword',
docx : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
eot : 'application/vnd.ms-fontobject',
epub : 'application/epub+zip',
gif : 'image/gif',
html : 'text/html',
ico : 'image/x-icon',
ics : 'text/calendar',
jar : 'application/java-archive',
jpeg : 'image/jpeg',
jpg : 'image/jpeg',
js : 'application/javascript',
json : 'application/json',
midi : 'audio/midi',
mpeg : 'video/mpeg',
mpkg : 'application/vnd.apple.installer+xml',
odp : 'application/vnd.oasis.opendocument.presentation',
ods : 'application/vnd.oasis.opendocument.spreadsheet',
odt : 'application/vnd.oasis.opendocument.text',
oga : 'audio/ogg',
ogv : 'video/ogg',
ogx : 'application/ogg',
otf : 'font/otf',
png : 'image/png',
pdf : 'application/pdf',
ppt : 'application/vnd.ms-powerpoint',
pptx : 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
rar : 'application/x-rar-compressed',
rtf : 'application/rtf',
sh : 'application/x-sh',
svg : 'image/svg+xml',
swf : 'application/x-shockwave-flash',
tar : 'application/x-tar',
tiff : 'image/tiff',
tif : 'image/tiff',
ts : 'application/typescript',
ttf : 'font/ttf',
vsd : 'application/vnd.visio',
wav : 'audio/x-wav',
weba : 'audio/webm',
webm : 'video/webm',
webp : 'image/webp',
woff : 'font/woff',
woff2 : 'font/woff2',
xhtml : 'application/xhtml+xml',
xls : 'application/vnd.ms-excel',
xlsx : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
xml : 'application/xml',
xul : 'application/vnd.mozilla.xul+xml',
zip : 'application/zip',
'3gp' : 'video/3gpp',
'7z' : 'application/x-7z-compressed',
};

/**
* Download on the client file served by the server
* @param {stream} data binary stream of the file
* @param {string} type the mime type extension of the file
* @param {string} filename the name of the file withour the extension
*/
service.download = (data, type, filename = 'fichier') => {
const name = (filename || 'fichier').concat('.', type);
const file = new Blob([data], { type : typeMime[type] || 'application/octet-stream' });

const url = window.URL || window.webkitURL;

const downloadLink = angular.element('<a></a>');
downloadLink.attr('href', url.createObjectURL(file));
downloadLink.attr('target', '_self');
downloadLink.attr('download', name);
downloadLink[0].click();
};

return service;
}
5 changes: 5 additions & 0 deletions client/src/js/services/LotService.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ function LotService(Api, $http, util) {
.then(util.unwrapHttpResponse);
};

lots.generateTags = (total) => {
return $http.get(`/lots/generate_tags/${total}`)
.then(util.unwrapHttpResponse);
};

/**
* @function computeLotWarningFlags()
* @description
Expand Down
14 changes: 14 additions & 0 deletions client/src/modules/stock/StockModal.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ function StockModalService(Modal) {
service.openLotScheduleModal = openLotScheduleModal;
service.openAMCCalculationModal = openAMCCalculationModal;
service.openConsumptionByLots = openConsumptionByLots;
service.openGenerateTagNumbers = openGenerateTagNumbers;

// generate tag numbers
function openGenerateTagNumbers(request) {
const params = angular.extend(modalParameters, {
templateUrl : 'modules/stock/entry/modals/generateTags.modal.html',
controller : 'GenerateTagsModalController',
controllerAs : '$ctrl',
resolve : { data : () => request },
});

const instance = Modal.open(params);
return instance.result;
}

/** create stock assign */
function openActionStockAssign(request) {
Expand Down
5 changes: 5 additions & 0 deletions client/src/modules/stock/entry/entry.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
<bh-change-depot on-select="StockCtrl.onChangeDepot(depot)"></bh-change-depot>
</a>
</bh-dropdown-menu-item>
<bh-dropdown-menu-item>
<a href="" ng-click="StockCtrl.generateTagNumbers()">
<i class="fa fa-barcode"></i> <span translate>STOCK.GENERATE_TAG_NUMBERS</span>
</a>
</bh-dropdown-menu-item>
</bh-dropdown-menu>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions client/src/modules/stock/entry/entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function StockEntryController(
vm.reset = reset;
vm.onDateChange = onDateChange;
vm.$loading = false;
vm.generateTagNumbers = StockModal.openGenerateTagNumbers;

vm.gridOptions = {
appScopeProvider : vm,
Expand Down
38 changes: 38 additions & 0 deletions client/src/modules/stock/entry/modals/generateTags.modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<form
name="GenerateTagNumbersForm"
bh-submit="$ctrl.submit(GenerateTagNumbersForm)"
novalidate>

<div class="modal-header">
<ol class="headercrumb">
<li class="static">
<i class="fa fa-barcode"></i>
<span translate>STOCK.GENERATE_TAG_NUMBERS</span>
</li>
</ol>
</div>

<div class="modal-body">
<div class="form-group">
<label for="totalTags" translate>FORM.LABELS.NUMBER_OF_TAGS</label>
<input
name="totalTags"
type="number"
step="1"
class="form-control"
ng-model="$ctrl.totalTags"
translate-attr="{ 'placeholder' : 'FORM.PLACEHOLDERS.TAG_NUMBER_TO_GENERATE' }">
<p class="form-text text-muted" translate>FORM.INFO.TAG_NUMBERS_TO_GENERATE</p>
</div>
</div>

<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$ctrl.cancel()" data-method="cancel" translate>
FORM.BUTTONS.CLOSE
</button>

<bh-loading-button loading-state="GenerateTagNumbersForm.$loading">
<span translate>FORM.BUTTONS.SUBMIT</span>
</bh-loading-button>
</div>
</form>
32 changes: 32 additions & 0 deletions client/src/modules/stock/entry/modals/generateTags.modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
angular.module('bhima.controllers')
.controller('GenerateTagsModalController', GenerateTagsModalController);

GenerateTagsModalController.$inject = [
'$uibModalInstance', 'NotifyService',
'LotService', 'DownloadLinkService',
];

function GenerateTagsModalController(Instance, Notify, Lots, DownloadLink) {
const vm = this;

vm.cancel = cancel;
vm.submit = submit;

// submit
function submit() {
if (vm.totalTags <= 0 || !vm.totalTags) { return null; }

return Lots.generateTags(vm.totalTags)
.then(file => {
DownloadLink.download(file, 'csv', 'barcodes');

Instance.close();
})
.catch(Notify.errorHandler);
}

// cancel
function cancel() {
Instance.close();
}
}
3 changes: 3 additions & 0 deletions server/config/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,9 @@ exports.configure = function configure(app) {
app.put('/beds/:id', bed.update);
app.delete('/beds/:id', bed.delete);

// on the fly tag numbers
app.get('/lots/generate_tags/:number', lots.generateTags);

// lots API
app.get('/lots/:uuid', lots.details);
app.put('/lots/:uuid', lots.update);
Expand Down
35 changes: 35 additions & 0 deletions server/controllers/stock/lots.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@
* @requires lib/db
* @requires lib/filter
*/
const fs = require('fs');
const _ = require('lodash');
const converter = require('json-2-csv');
const tempy = require('tempy');
const debug = require('debug')('bhima:lots');
const moment = require('moment');
const db = require('../../lib/db');
const barcode = require('../../lib/barcode');
const util = require('../../lib/util');
const FilterParser = require('../../lib/filter');
const identifiers = require('../../config/identifiers');

const detailsQuery = `
SELECT
Expand All @@ -37,6 +43,7 @@ exports.getAllDupes = getAllDupes;
exports.merge = merge;
exports.autoMerge = autoMerge;
exports.autoMergeZero = autoMergeZero;
exports.generateTags = generateTags;

function getLotTags(bid) {
const queryTags = `
Expand Down Expand Up @@ -442,3 +449,31 @@ function assignments(req, res, next) {
.catch(next)
.done();
}

/**
* GET /lots/generate_tags/:number
*
* @description
* Returns generated tag number
*/
async function generateTags(req, res, next) {

try {
const totalTags = req.params.number;
const { key } = identifiers.LOT;
const tagNumbers = [];

for (let i = 0; i < totalTags; i++) {
tagNumbers.push({ barcode : barcode.generate(key, util.uuid()) });
}

const data = await converter.json2csvAsync(tagNumbers, { trimHeaderFields : true, trimFieldValues : true });
const tmpDocumentsFile = tempy.file({ name : 'barcodes.csv' });
await fs.promises.writeFile(tmpDocumentsFile, data);
res.attachment(tmpDocumentsFile);
res.download(tmpDocumentsFile);
} catch (error) {
next(error);
}

}

0 comments on commit f2358a7

Please sign in to comment.